diff --git a/.gitignore b/.gitignore index 9c8ffbab24c0640598a7a64c358c0658e26b7f38..0fb47b974bbfb8e2e0fcfd15bc653f85e48c437e 100644 --- a/.gitignore +++ b/.gitignore @@ -28,10 +28,11 @@ /com.oracle.truffle.r.native/include/*.h /com.oracle.truffle.r.native/include/R_ext/*.h /com.oracle.truffle.r.native/include/linked -/com.oracle.truffle.r.native/fficall/jni.done +/com.oracle.truffle.r.native/fficall/fficall.done /com.oracle.truffle.r.native/fficall/jniboot.done /com.oracle.truffle.r.native.recommended/install.recommended /com.oracle.truffle.r.test.native/packages/copy_recommended +/com.oracle.truffle.r.test.native/packages/repo/* /com.oracle.truffle.r.test.native/packages/recommended /com.oracle.truffle.r.test.native/packages/*/lib/* /com.oracle.truffle.r.test.native/urand/lib/liburand.so @@ -88,6 +89,7 @@ output.txt output.cfg .cfg **/nbproject/** + **/build.xml /scratch/ /test.fastr/ @@ -127,10 +129,14 @@ R.tokens findbugs.html test_gnur test_fastr -lib.install.cran* +lib.install.packages* package.blacklist *.ll *.su *.bc com.oracle.truffle.r.test.native/embedded/lib bench-results.json +com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/asTests.R +com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/coerceTests.R +com.oracle.truffle.r.native/version.built +documentation/.pydevproject diff --git a/README.md b/README.md index 6c421a3f83d78fd2e3d423fde7eefce5489c1478..ae5a5aa685acd0255a307ead2163496fc91c32fb 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ FastR is primarily aimed at long-running applications. The runtime performance b Building FastR from source is supported on Mac OS X (El Capitan onwards), and various flavors of Linux. FastR uses a build tool called `mx` (cf `maven`) which can be downloaded from [here](http://github.com/graalvm/mx). -`mx` manages software in _suites_, which are normally one-to-one with a `git` repository. FastR depends fundamentally on the [truffle](http://github.com/graalvm/truffle) suite. However, performance also depends on the [Graal compiler](http://github.com/graalvm/graal-core) as without it, FastR operates in interpreted mode only. The conventional way to arrange the Git repos (suites) is as siblings in a parent directory, which we will call `FASTR_HOME`. +`mx` manages software in _suites_, which are normally one-to-one with a `git` repository. FastR depends fundamentally on the [truffle](http://github.com/graalvm/truffle) suite. However, performance also depends on the [Graal compiler](http://github.com/graalvm/graal) as without it, FastR operates in interpreted mode only. The conventional way to arrange the Git repos (suites) is as siblings in a parent directory, which we will call `FASTR_HOME`. ## Pre-Requisites FastR shares some code with GnuR, for example, the default packages and the Blas library. Therefore, a version of GnuR (currently diff --git a/ci.hocon b/ci.hocon index 9d80f57bdfee35b5ed75c817ad196986f2f46722..9e85b47df51380e4d3737037c9d54df84d1f5a1d 100644 --- a/ci.hocon +++ b/ci.hocon @@ -6,7 +6,7 @@ # java 7 is needed by Truffle (for now) java7 : {name : oraclejdk, version : "7", platformspecific: true} # java 8 must be a jvmci enabled variant -java8 : {name : labsjdk, version : "8u121-jvmci-0.24", platformspecific: true} +java8 : {name : labsjdk, version : "8-jvmci-latest", platformspecific: true} java8Downloads : { downloads : { @@ -34,7 +34,7 @@ logfiles : [ pkgEnvironment: { environment : { PKG_INCLUDE_FLAGS_OVERRIDE : """-I/cm/shared/apps/zlib/1.2.8/include -I/cm/shared/apps/bzip2/1.0.6/include -I/cm/shared/apps/xz/5.2.2/include -I/cm/shared/apps/pcre/8.38/include -I/cm/shared/apps/curl/7.50.1/include""" - PKG_LDFLAGS_OVERRIDE : """"-L/cm/shared/apps/zlib/1.2.8/lib -L/cm/shared/apps/bzip2/1.0.6/lib -L/cm/shared/apps/xz/5.2.2/lib -L/cm/shared/apps/pcre/8.38/lib -L/cm/shared/apps/curl/7.50.1//lib -L/cm/shared/apps/gcc/4.9.1/lib64"""" + PKG_LDFLAGS_OVERRIDE : """"-L/cm/shared/apps/zlib/1.2.8/lib -L/cm/shared/apps/bzip2/1.0.6/lib -L/cm/shared/apps/xz/5.2.2/lib -L/cm/shared/apps/pcre/8.38/lib -L/cm/shared/apps/curl/7.50.1/lib -L/cm/shared/apps/gcc/4.9.1/lib64"""" } } @@ -49,6 +49,7 @@ packagesLinux : ${pkgEnvironment} { readline : "==6.3" pcre : ">=8.38" z : ">=1.2.8" + curl : ">=7.50.1" } } @@ -58,6 +59,7 @@ packagesDarwin : { "xz" : "" "pcre" : "" "z" : "" + "curl" : "" } # Common settings for all builds but note that it uses the Linux package settings, @@ -106,6 +108,22 @@ gateTestDarwin : ${gateTestCommon} ${darwinEnvironment} { } } +gateTestLinuxNFI : ${gateTestCommon} { + environment : { + FASTR_RFFI : "nfi" + } +} + +gateTestManagedLinux: ${common} { + environment : { + FASTR_MANAGED : "true" + } + run : [ + ${gateCmd} ["Versions,JDKReleaseInfo,BuildJavaWithJavac"] + ] +} + + # This performs a number of "style" checks on the code to ensure it confirms to the project standards. gateStyle : ${common} { @@ -130,16 +148,27 @@ rbcheck : ${common} { run : [ ${gateCmd} ["Versions,JDKReleaseInfo,BuildJavaWithJavac"] ["mx", "rbcheck"] - ["mx", "rbdiag", "-n", "-m"] + ["mx", "rbdiag"] + ] +} + +internalPkgtest: ${common} { + run : [ + ["mx", "build"] + ["mx", "pkgtest", "--repos", "FASTR", "--pkg-filelist", "com.oracle.truffle.r.test.native/packages/pkg-filelist"] ] + logs: ${common.logs} } # The standard set of gate builds. N.B. the style/builtin checks are only run on Linux as they are not OS-dependent. builds = [ - ${gateTestLinux} {capabilities : [linux, amd64, fast], targets : [gate, post-merge], name: "gate-test-linux-amd64"} - ${gateTestNoSpecialsLinux} {capabilities : [linux, amd64, fast], targets : [gate, post-merge], name: "gate-test-linux-amd64-nospecials"} - ${gateTestDarwin} {capabilities : [darwin, amd64], targets : [gate, post-merge], name: "gate-test-darwin-amd64"} - ${gateStyle} {capabilities : [linux, amd64], targets : [gate, post-merge], name: "gate-style-linux-amd64"} - ${rbcheck} {capabilities : [linux, amd64], targets : [gate, post-merge], name: "gate-rbcheck-linux-amd64"} + ${gateTestLinux} {capabilities : [linux, amd64, fast], targets : [gate], name: "gate-test-linux-amd64"} + ${gateTestLinuxNFI} {capabilities : [linux, amd64, fast], targets : [gate], name: "gate-test-linux-nfi-amd64"} + ${gateTestNoSpecialsLinux} {capabilities : [linux, amd64, fast], targets : [gate], name: "gate-test-linux-amd64-nospecials"} + ${gateTestDarwin} {capabilities : [darwin, amd64], targets : [gate], name: "gate-test-darwin-amd64"} + ${gateStyle} {capabilities : [linux, amd64], targets : [gate], name: "gate-style-linux-amd64"} + ${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"} ] 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 9f8a4b53b49ee82605bc9579d0c63b009ea9b7ba..a1027bfdc9013d56578f9aab0f743c2c6e10bd77 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 @@ -42,6 +42,7 @@ import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.java.JavaInterop; import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.Node; @@ -145,8 +146,7 @@ final class REngine implements Engine, Engine.Timings { } static REngine create(RContext context) { - REngine engine = new REngine(context); - return engine; + return new REngine(context); } @Override @@ -165,7 +165,7 @@ final class REngine implements Engine, Engine.Timings { REnvironment.baseInitialize(baseFrame, globalFrame); RBuiltinPackages.loadBase(baseFrame); RGraphics.initialize(); - if (FastROptions.LoadBase.getBooleanValue()) { + if (FastROptions.LoadProfiles.getBooleanValue()) { /* * eval the system/site/user profiles. Experimentally GnuR does not report warnings * during system profile evaluation, but does for the site/user profiles. @@ -296,9 +296,23 @@ final class REngine implements Engine, Engine.Timings { } @Override + @SuppressWarnings("deprecation") public CallTarget parseToCallTarget(Source source, MaterializedFrame executionFrame) throws ParseException { - List<RSyntaxNode> statements = parseImpl(source); - return Truffle.getRuntime().createCallTarget(new PolyglotEngineRootNode(statements, createSourceSection(source, statements), executionFrame)); + if (source == Engine.GET_CONTEXT) { + /* + * The "get context" operations should be executed with as little influence on the + * actual engine as possible, therefore this special case takes care of it explicitly. + */ + return Truffle.getRuntime().createCallTarget(new RootNode(TruffleRLanguage.class, source.createUnavailableSection(), new FrameDescriptor()) { + @Override + public Object execute(VirtualFrame frame) { + return JavaInterop.asTruffleValue(context); + } + }); + } else { + List<RSyntaxNode> statements = parseImpl(source); + return Truffle.getRuntime().createCallTarget(new PolyglotEngineRootNode(statements, createSourceSection(source, statements), executionFrame)); + } } private static SourceSection createSourceSection(Source source, List<RSyntaxNode> statements) { @@ -345,6 +359,7 @@ final class REngine implements Engine, Engine.Timings { @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode(); + @SuppressWarnings("deprecation") PolyglotEngineRootNode(List<RSyntaxNode> statements, SourceSection sourceSection, MaterializedFrame executionFrame) { super(TruffleRLanguage.class, sourceSection, new FrameDescriptor()); // can't print if initializing the system in embedded mode (no builtins yet) @@ -398,8 +413,12 @@ final class REngine implements Engine, Engine.Timings { for (int i = 0; i < exprs.getLength(); i++) { Object obj = exprs.getDataAt(i); if (obj instanceof RSymbol) { - result = ReadVariableNode.lookupAny(((RSymbol) obj).getName(), envir.getFrame(), false); + String identifier = ((RSymbol) obj).getName(); + result = ReadVariableNode.lookupAny(identifier, envir.getFrame(), false); caller.setVisibility(true); + if (result == null) { + throw RError.error(RError.SHOW_CALLER, RError.Message.ARGUMENT_MISSING, identifier); + } } else if (obj instanceof RLanguage) { result = evalNode(((RLanguage) obj).getRep().asRSyntaxNode(), envir, caller); } else { @@ -528,6 +547,7 @@ final class REngine implements Engine, Engine.Timings { @Child private GetVisibilityNode visibility = GetVisibilityNode.create(); @Child private SetVisibilityNode setVisibility = SetVisibilityNode.create(); + @SuppressWarnings("deprecation") protected AnonymousRootNode(RNode body, String description, boolean printResult, boolean topLevel) { super(TruffleRLanguage.class, null, new FrameDescriptor()); this.body = body; 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 0c7606c8f3ef30a06a7a5c0eecb5c113041a1753..ed08560e6b131206d1d416026031cdf0a9c24215 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 @@ -54,8 +54,10 @@ import com.oracle.truffle.r.nodes.builtin.helpers.DebugHandling; import com.oracle.truffle.r.nodes.builtin.helpers.TraceHandling; import com.oracle.truffle.r.nodes.control.AbstractLoopNode; import com.oracle.truffle.r.nodes.control.BlockNode; +import com.oracle.truffle.r.nodes.control.ForNode; import com.oracle.truffle.r.nodes.control.IfNode; import com.oracle.truffle.r.nodes.control.ReplacementDispatchNode; +import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; import com.oracle.truffle.r.nodes.function.FunctionExpressionNode; import com.oracle.truffle.r.nodes.function.RCallNode; @@ -70,6 +72,7 @@ import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntimeASTAccess; import com.oracle.truffle.r.runtime.RSrcref; import com.oracle.truffle.r.runtime.ReturnException; +import com.oracle.truffle.r.runtime.RootWithBody; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.context.Engine; import com.oracle.truffle.r.runtime.context.RContext; @@ -85,6 +88,7 @@ import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RCodeBuilder; @@ -530,13 +534,15 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { return true; } else { // single statement block, variable parent - return parent instanceof FunctionDefinitionNode || parent instanceof IfNode || parent instanceof AbstractLoopNode; + // note: RepeatingNode is not a RSyntaxElement but the body of a loop is + // under the repeating node ! + return parent instanceof FunctionDefinitionNode || parent instanceof RootWithBody || parent instanceof IfNode || parent instanceof AbstractLoopNode || ForNode.isLoopBody(node); } } case "RootTag": { Node parent = ((RInstrumentableNode) node).unwrapParent(); - return parent instanceof FunctionDefinitionNode; + return parent instanceof FunctionDefinitionNode || parent instanceof RootWithBody; } case "LoopTag": @@ -559,16 +565,19 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { } @Override + @TruffleBoundary public boolean enableDebug(RFunction func, boolean once) { return DebugHandling.enableDebug(func, "", RNull.instance, once, false); } @Override + @TruffleBoundary public boolean isDebugged(RFunction func) { return DebugHandling.isDebugged(func); } @Override + @TruffleBoundary public boolean disableDebug(RFunction func) { return DebugHandling.undebug(func); } @@ -716,4 +725,9 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { public Class<? extends TruffleLanguage<?>> getTruffleRLanguage() { return TruffleRLanguage.class; } + + @Override + public RAbstractStringVector getClassHierarchy(RAttributable value) { + return ClassHierarchyNode.getClassHierarchy(value); + } } 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 c6ead8aaa2a9849ee64a13b67167ae541313634b..ee9a96bf866b4d36ef569b37630685bcfd81a6af 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 @@ -28,11 +28,13 @@ import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.Instrumenter; import com.oracle.truffle.api.instrumentation.ProvidedTags; import com.oracle.truffle.api.instrumentation.StandardTags; +import com.oracle.truffle.api.metadata.ScopeProvider; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.SourceSection; @@ -44,6 +46,7 @@ import com.oracle.truffle.r.nodes.qirinterface.QIRInterface; import com.oracle.truffle.r.runtime.ExitException; import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.RAccuracyInfo; +import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.Utils; @@ -54,6 +57,7 @@ import com.oracle.truffle.r.runtime.context.RContext.RCloseable; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RTypedValue; +import com.oracle.truffle.r.runtime.env.RScope; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; import com.oracle.truffle.r.runtime.nodes.RBaseNode; @@ -63,7 +67,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; */ @TruffleLanguage.Registration(name = "R", version = "0.1", mimeType = {RRuntime.R_APP_MIME, RRuntime.R_TEXT_MIME}, interactive = true) @ProvidedTags({StandardTags.CallTag.class, StandardTags.StatementTag.class, StandardTags.RootTag.class, RSyntaxTags.LoopTag.class}) -public final class TruffleRLanguage extends TruffleLanguage<RContext> { +public final class TruffleRLanguage extends TruffleLanguage<RContext> implements ScopeProvider<RContext> { /** * The choice of {@link RFFIFactory} is made statically so that it is bound into an AOT-compiled @@ -72,7 +76,6 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> { */ private static void initialize() { try { - RFFIFactory.initialize(); Locale.setDefault(Locale.ROOT); RAccuracyInfo.initialize(); } catch (Throwable t) { @@ -92,11 +95,12 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> { private static boolean systemInitialized; - public static final TruffleRLanguage INSTANCE = new TruffleRLanguage(); + public static TruffleRLanguage INSTANCE; public static final String MIME = RRuntime.R_APP_MIME; - private TruffleRLanguage() { + public TruffleRLanguage() { + INSTANCE = this; } @Override @@ -132,17 +136,21 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> { @Override protected String toString(RContext context, Object value) { - // Btw debugger passes result of TruffleRLanguage.findMetaObject() to this method too - if (value instanceof String) { - return (String) value; - } - if (value instanceof RPromise) { - RPromise promise = (RPromise) value; + // the debugger also passes result of TruffleRLanguage.findMetaObject() to this method + Object unwrapped = value; + if (unwrapped instanceof RPromise) { + RPromise promise = (RPromise) unwrapped; if (promise.isEvaluated()) { - value = promise.getValue(); + unwrapped = promise.getValue(); } } - return RRuntime.toString(value); + if (unwrapped instanceof String) { + return (String) unwrapped; + } + if (unwrapped instanceof RTypedValue) { + return RDeparse.deparse(unwrapped); + } + return RRuntime.toString(unwrapped); } @Override @@ -187,8 +195,8 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> { return null; } - @SuppressWarnings("try") @Override + @SuppressWarnings({"try", "deprecation"}) protected CallTarget parse(ParsingRequest request) throws Exception { CompilerAsserts.neverPartOfCompilation(); try (RCloseable c = RContext.withinContext(findContext(createFindContextNode()))) { @@ -230,11 +238,18 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> { } // TODO: why isn't the original method public? + @SuppressWarnings("deprecation") public Node actuallyCreateFindContextNode() { return createFindContextNode(); } + @SuppressWarnings("deprecation") public RContext actuallyFindContext0(Node contextNode) { return findContext(contextNode); } + + @Override + public AbstractScope findScope(RContext langContext, Node node, Frame frame) { + return RScope.createScope(node, frame); + } } diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java new file mode 100644 index 0000000000000000000000000000000000000000..b028bd676da709688dd0328c54b998517824e21b --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java @@ -0,0 +1,77 @@ +/* + * 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.context.RContext; +import com.oracle.truffle.r.runtime.context.RContext.RCloseable; +import com.oracle.truffle.r.runtime.env.frame.ActiveBinding; + +@MessageResolution(receiverType = ActiveBinding.class, language = TruffleRLanguage.class) +public class ActiveBindingMR { + @Resolve(message = "IS_BOXED") + public abstract static class ActiveBindingIsBoxedNode extends Node { + protected Object access(@SuppressWarnings("unused") ActiveBinding receiver) { + return true; + } + } + + @Resolve(message = "HAS_SIZE") + public abstract static class ActiveBindingHasSizeNode extends Node { + protected Object access(@SuppressWarnings("unused") ActiveBinding receiver) { + return false; + } + } + + @Resolve(message = "IS_NULL") + public abstract static class ActiveBindingIsNullNode extends Node { + protected Object access(@SuppressWarnings("unused") ActiveBinding receiver) { + return false; + } + } + + @Resolve(message = "UNBOX") + public abstract static class ActiveBindingUnboxNode extends Node { + @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode(); + + @SuppressWarnings("try") + protected Object access(ActiveBinding receiver) { + try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) { + return receiver.readValue(); + } + } + } + + @CanResolve + public abstract static class ActiveBindingCheck extends Node { + + protected static boolean test(TruffleObject receiver) { + return receiver instanceof ActiveBinding; + } + } +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/CaptureNamesImplMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/CaptureNamesImplMR.java new file mode 100644 index 0000000000000000000000000000000000000000..5063771196f2e8e7d5113cced1325945a591b61e --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/CaptureNamesImplMR.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017, 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.frame.VirtualFrame; +import com.oracle.truffle.api.interop.CanResolve; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.InteropException; +import com.oracle.truffle.api.interop.Message; +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.engine.interop.ffi.nfi.TruffleNFI_PCRE; +import com.oracle.truffle.r.runtime.RInternalError; + +@MessageResolution(receiverType = TruffleNFI_PCRE.TruffleNFI_GetCaptureNamesNode.CaptureNamesImpl.class, language = TruffleRLanguage.class) +public class CaptureNamesImplMR { + @CanResolve + public abstract static class CaptureNamesImplCheck extends Node { + + protected static boolean test(TruffleObject receiver) { + return receiver instanceof TruffleNFI_PCRE.TruffleNFI_GetCaptureNamesNode.CaptureNamesImpl; + } + } + + @Resolve(message = "EXECUTE") + public abstract static class CaptureNamesImplExecute extends Node { + protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_PCRE.TruffleNFI_GetCaptureNamesNode.CaptureNamesImpl receiver, Object[] arguments) { + try { + Object arg1 = arguments[1]; + if (arg1 instanceof TruffleObject) { + if (ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), (TruffleObject) arg1)) { + arg1 = null; + } else { + arg1 = ForeignAccess.sendUnbox(Message.UNBOX.createNode(), (TruffleObject) arg1); + } + } + receiver.addName((int) arguments[0], (String) arg1); + return receiver; + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/GlobUpCallImplMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/GlobUpCallImplMR.java new file mode 100644 index 0000000000000000000000000000000000000000..3a614c0a7bcdaff7838f6f5a0e33b78a235ccab8 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/GlobUpCallImplMR.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017, 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.frame.VirtualFrame; +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.engine.interop.ffi.nfi.TruffleNFI_Base; + +@MessageResolution(receiverType = TruffleNFI_Base.TruffleNFI_GlobNode.GlobUpCallImpl.class, language = TruffleRLanguage.class) +public class GlobUpCallImplMR { + @CanResolve + public abstract static class GlobUpCallImplCheck extends Node { + + protected static boolean test(TruffleObject receiver) { + return receiver instanceof TruffleNFI_Base.TruffleNFI_GlobNode.GlobUpCallImpl; + } + } + + @Resolve(message = "EXECUTE") + public abstract static class GlobUpCallImplExecute extends Node { + protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_Base.TruffleNFI_GlobNode.GlobUpCallImpl receiver, Object[] arguments) { + receiver.addPath((String) arguments[0]); + return receiver; + } + } +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/MakeResultImplMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/MakeResultImplMR.java new file mode 100644 index 0000000000000000000000000000000000000000..34c97f9c38af9280a2cee84030ce905b28957ae9 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/MakeResultImplMR.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017, 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.frame.VirtualFrame; +import com.oracle.truffle.api.interop.CanResolve; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.InteropException; +import com.oracle.truffle.api.interop.Message; +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.engine.interop.ffi.nfi.TruffleNFI_PCRE; +import com.oracle.truffle.r.runtime.RInternalError; + +@MessageResolution(receiverType = TruffleNFI_PCRE.TruffleNFI_CompileNode.MakeResultImpl.class, language = TruffleRLanguage.class) +public class MakeResultImplMR { + @CanResolve + public abstract static class MakeResultImplCheck extends Node { + + protected static boolean test(TruffleObject receiver) { + return receiver instanceof TruffleNFI_PCRE.TruffleNFI_CompileNode.MakeResultImpl; + } + } + + @Resolve(message = "EXECUTE") + public abstract static class MakeResultImplExecute extends Node { + protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_PCRE.TruffleNFI_CompileNode.MakeResultImpl receiver, Object[] arguments) { + try { + Object arg1 = arguments[1]; + if (arg1 instanceof TruffleObject) { + if (ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), (TruffleObject) arg1)) { + arg1 = null; + } else { + arg1 = ForeignAccess.sendUnbox(Message.UNBOX.createNode(), (TruffleObject) arg1); + } + } + receiver.makeresult((long) arguments[0], (String) arg1, (int) arguments[2]); + return receiver; + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java index 3cb4647f517c898ced0c35480b2a3aae55dbd610..c5ee552ba380672fe4fe7156fee47151cf430807 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.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 @@ -28,23 +28,27 @@ import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.ForeignAccess; -import com.oracle.truffle.api.interop.ForeignAccess.Factory18; +import com.oracle.truffle.api.interop.ForeignAccess.Factory26; import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.r.engine.TruffleRLanguage; import com.oracle.truffle.r.engine.interop.RAbstractVectorAccessFactoryFactory.VectorReadNodeGen; import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode; import com.oracle.truffle.r.nodes.control.RLengthNode; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.context.RContext.RCloseable; import com.oracle.truffle.r.runtime.data.RLogical; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -public final class RAbstractVectorAccessFactory implements Factory18 { +public final class RAbstractVectorAccessFactory implements Factory26 { static class VectorSizeNode extends RootNode { @Child private RLengthNode lengthNode = RLengthNode.create(); + @SuppressWarnings("deprecation") VectorSizeNode() { super(TruffleRLanguage.class, null, null); } @@ -60,17 +64,22 @@ public final class RAbstractVectorAccessFactory implements Factory18 { @CompilationFinal private boolean lengthAccess; @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); @Child private RLengthNode lengthNode = RLengthNode.create(); + @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode(); + @SuppressWarnings("deprecation") VectorReadNode() { super(TruffleRLanguage.class, null, null); this.lengthAccess = false; } @Override + @SuppressWarnings("try") public final Object execute(VirtualFrame frame) { - Object label = ForeignAccess.getArguments(frame).get(0); - Object receiver = ForeignAccess.getReceiver(frame); - return execute(frame, receiver, label); + try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) { + Object label = ForeignAccess.getArguments(frame).get(0); + Object receiver = ForeignAccess.getReceiver(frame); + return execute(frame, receiver, label); + } } protected abstract Object execute(VirtualFrame frame, Object reciever, Object label); @@ -87,6 +96,7 @@ public final class RAbstractVectorAccessFactory implements Factory18 { } private abstract class InteropRootNode extends RootNode { + @SuppressWarnings("deprecation") InteropRootNode() { super(TruffleRLanguage.class, null, null); } @@ -178,4 +188,9 @@ public final class RAbstractVectorAccessFactory implements Factory18 { public CallTarget accessKeys() { return null; } + + @Override + public CallTarget accessKeyInfo() { + return null; + } } diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RArgsValuesAndNamesMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RArgsValuesAndNamesMR.java new file mode 100644 index 0000000000000000000000000000000000000000..5eafbc04ce58622d9989777137668b3345bc8047 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RArgsValuesAndNamesMR.java @@ -0,0 +1,63 @@ +/* + * 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.RArgsValuesAndNames; + +@MessageResolution(receiverType = RArgsValuesAndNames.class, language = TruffleRLanguage.class) +public class RArgsValuesAndNamesMR { + @Resolve(message = "IS_BOXED") + public abstract static class RArgsValuesAndNamesIsBoxedNode extends Node { + protected Object access(@SuppressWarnings("unused") RArgsValuesAndNames receiver) { + return false; + } + } + + @Resolve(message = "HAS_SIZE") + public abstract static class RArgsValuesAndNamesHasSizeNode extends Node { + protected Object access(@SuppressWarnings("unused") RArgsValuesAndNames receiver) { + return true; + } + } + + @Resolve(message = "IS_NULL") + public abstract static class RArgsValuesAndNamesIsNullNode extends Node { + protected Object access(@SuppressWarnings("unused") RArgsValuesAndNames receiver) { + return false; + } + } + + @CanResolve + public abstract static class RArgsValuesAndNamesCheck extends Node { + + protected static boolean test(TruffleObject receiver) { + return receiver instanceof RArgsValuesAndNames; + } + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/GridRFFI.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RConnectionMR.java similarity index 59% rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/GridRFFI.java rename to com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RConnectionMR.java index 43082161ce14e5abaca49d55af3ce7b998993ad2..45df6f9f1920f0b49d8069efb5df6fb6bed57ed2 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/GridRFFI.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RConnectionMR.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -20,30 +20,23 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.ffi; +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.TruffleObject; import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.engine.TruffleRLanguage; +import com.oracle.truffle.r.runtime.conn.RConnection; -public interface GridRFFI { - abstract class InitGridNode extends Node { - public abstract Object execute(REnvironment gridEvalEnv); +@MessageResolution(receiverType = RConnection.class, language = TruffleRLanguage.class) +public class RConnectionMR { + @CanResolve + public abstract static class RConnection extends Node { - public static InitGridNode create() { - return RFFIFactory.getRFFI().getGridRFFI().createInitGridNode(); + protected static boolean test(TruffleObject receiver) { + return receiver instanceof RConnection; } } - abstract class KillGridNode extends Node { - - public abstract Object execute(); - - public static KillGridNode create() { - return RFFIFactory.getRFFI().getGridRFFI().createKillGridNode(); - } - } - - InitGridNode createInitGridNode(); - - KillGridNode createKillGridNode(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToIntVectorClosure.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RContextMR.java similarity index 58% rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToIntVectorClosure.java rename to com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RContextMR.java index 12ac3e31b811aae81c5fc76e2732dd2f7aefd08f..19ed14c1253f992a27cb3bff458f80a54ece9229 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToIntVectorClosure.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RContextMR.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -20,24 +20,23 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.data.closures; +package com.oracle.truffle.r.engine.interop; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; +import com.oracle.truffle.api.interop.CanResolve; +import com.oracle.truffle.api.interop.MessageResolution; +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.context.RContext; -final class RLogicalToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector { +@MessageResolution(receiverType = RContext.class, language = TruffleRLanguage.class) +public class RContextMR { + @CanResolve + public abstract static class RContext extends Node { - RLogicalToIntVectorClosure(RAbstractLogicalVector vector) { - super(vector); - } - - @Override - public int getDataAt(int index) { - byte data = ((RAbstractLogicalVector) vector).getDataAt(index); - if (!vector.isComplete() && RRuntime.isNA(data)) { - return RRuntime.INT_NA; + protected static boolean test(TruffleObject receiver) { + return receiver instanceof RContext; } - return data; } + } diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java index 5372d38a23acdb1431a705ce8c7d29471d0d19da..c3e7e288f8dc10217a4444067a0a0c2290d0a271 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java @@ -22,6 +22,8 @@ */ package com.oracle.truffle.r.engine.interop; +import static com.oracle.truffle.r.engine.interop.Utils.javaToRPrimitive; + import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.CanResolve; import com.oracle.truffle.api.interop.MessageResolution; @@ -32,7 +34,6 @@ import com.oracle.truffle.r.engine.TruffleRLanguage; import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode; import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode; -import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.context.RContext.RCloseable; import com.oracle.truffle.r.runtime.env.REnvironment; @@ -82,20 +83,7 @@ public class REnvironmentMR { @SuppressWarnings("try") protected Object access(VirtualFrame frame, REnvironment receiver, String field, Object valueObj) { try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) { - Object value = valueObj; - if (value instanceof Short) { - value = (int) ((Short) value).shortValue(); - } else if (value instanceof Float) { - float floatValue = ((Float) value).floatValue(); - value = new Double(floatValue); - } else if (value instanceof Boolean) { - boolean booleanValue = ((Boolean) value).booleanValue(); - value = booleanValue ? RRuntime.LOGICAL_TRUE : RRuntime.LOGICAL_FALSE; - } else if (value instanceof Character) { - value = (int) ((Character) value).charValue(); - } else if (value instanceof Byte) { - value = (int) ((Byte) value).byteValue(); - } + Object value = javaToRPrimitive(valueObj); Object x = extract.apply(frame, receiver, new Object[]{field}, value); return x; } 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 1b8aca885df504ab57b6b46bcac74eec7523a8b6..9082fefc169f2c968b3d4eb6e6b27411e2ed162c 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 @@ -23,132 +23,117 @@ package com.oracle.truffle.r.engine.interop; import com.oracle.truffle.api.CompilerAsserts; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.MessageResolution; -import com.oracle.truffle.api.interop.TruffleObject; -import com.oracle.truffle.api.vm.PolyglotEngine; 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.RExternalPtr; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RInteger; +import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RList; 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.RSymbol; import com.oracle.truffle.r.runtime.data.RTruffleObject; import com.oracle.truffle.r.runtime.data.RUnboundValue; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.env.frame.ActiveBinding; import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper; import com.oracle.truffle.r.runtime.ffi.DLL; /** - * A {@link ForeignAccess} instance captures the {@link Thread} that creates it and all uses are - * checked against the current thread. Therefore, in a world with multiple {@link PolyglotEngine}s, - * aka multiple {@link Thread} and {@link RContext} instances, it is not possible to use a simple - * global constant value for the {@link ForeignAccess} instance that could be associated directly - * with the {@link TruffleObject} class. - * - * This factory provides a generic solution for all FastR types (all of which are - * {@link TruffleObject}s), at some cost in performance. - * * For most types we use the {@link MessageResolution} facility to automatically generate the * factory for creating the {@link ForeignAccess} instance. The exceptions are the (many) subclasses * of {@link RAbstractVector} as these have the same handling but the generator cannot handle * abstract classes. - * */ public final class RForeignAccessFactoryImpl implements RForeignAccessFactory { - private static final class TableEntry { - private final Class<? extends RTruffleObject> clazz; // for sanity check - private final ForeignAccess foreignAccess; - /** - * {@link PolyglotEngine} checks the thread on a {@link ForeignAccess}. - */ - private final Thread thread; - private TableEntry(Class<? extends RTruffleObject> clazz, ForeignAccess foreignAccess) { - this.clazz = clazz; - this.foreignAccess = foreignAccess; - this.thread = Thread.currentThread(); - } - } - - private final TableEntry[] table = new TableEntry[32]; - int tableIndex; - - private synchronized ForeignAccess get(RTruffleObject obj) { - Class<? extends RTruffleObject> objclazz = obj.getClass(); - Thread thread = Thread.currentThread(); - for (int i = 0; i < tableIndex; i++) { - TableEntry te = table[i]; - if (te.clazz == objclazz && te.thread == thread) { - return te.foreignAccess; - } - } - return createForeignAccess(objclazz); - } + @Override + public ForeignAccess getForeignAccess(RTruffleObject obj) { + CompilerAsserts.neverPartOfCompilation("getForeignAccess"); + if (obj instanceof RNull) { + return RNullMRForeign.ACCESS; + } else if (obj instanceof RList) { + return RListMRForeign.ACCESS; + } else if (obj instanceof REnvironment) { + return REnvironmentMRForeign.ACCESS; + } else if (obj instanceof RPairList) { + return RPairListMRForeign.ACCESS; + } else if (obj instanceof RFunction) { + return RFunctionMRForeign.ACCESS; + } else if (obj instanceof DLL.DLLInfo) { + return DLLInfoMRForeign.ACCESS; + } else if (obj instanceof DLL.DotSymbol) { + return DLLDotSymbolMRForeign.ACCESS; + } else if (obj instanceof RSymbol) { + return RSymbolMRForeign.ACCESS; + } else if (obj instanceof RExternalPtr) { + return RExternalPtrMRForeign.ACCESS; + } else if (obj instanceof RUnboundValue) { + return RUnboundValueMRForeign.ACCESS; + } else if (obj instanceof NativeRawArray) { + return NativeRawArrayMRForeign.ACCESS; + } else if (obj instanceof NativeLogicalArray) { + return NativeLogicalArrayMRForeign.ACCESS; + } else if (obj instanceof NativeCharArray) { + return NativeCharArrayMRForeign.ACCESS; + } else if (obj instanceof NativeDoubleArray) { + return NativeDoubleArrayMRForeign.ACCESS; + } else if (obj instanceof NativeIntegerArray) { + return NativeIntegerArrayMRForeign.ACCESS; + } else if (obj instanceof RInteger) { + return RIntegerMRForeign.ACCESS; + } else if (obj instanceof RDouble) { + return RDoubleMRForeign.ACCESS; + } else if (obj instanceof CharSXPWrapper) { + return CharSXPWrapperMRForeign.ACCESS; + } else if (obj instanceof RConnection) { + return RConnectionMRForeign.ACCESS; + } else if (obj instanceof RContext) { + return RContextMRForeign.ACCESS; + } else if (obj instanceof TruffleNFI_Base.TruffleNFI_UnameNode.UnameUpCallImpl) { + return UnameUpCallImplMRForeign.ACCESS; + } else if (obj instanceof TruffleNFI_Base.TruffleNFI_ReadlinkNode.SetResultImpl) { + return SetResultImplMRForeign.ACCESS; + } else if (obj instanceof TruffleNFI_Base.TruffleNFI_GlobNode.GlobUpCallImpl) { + return GlobUpCallImplMRForeign.ACCESS; + } else if (obj instanceof TruffleNFI_PCRE.TruffleNFI_CompileNode.MakeResultImpl) { + return MakeResultImplMRForeign.ACCESS; + } else if (obj instanceof TruffleNFI_PCRE.TruffleNFI_GetCaptureNamesNode.CaptureNamesImpl) { + return CaptureNamesImplMRForeign.ACCESS; + } else if (obj instanceof RS4Object) { + return RS4ObjectMRForeign.ACCESS; + } else if (obj instanceof RPromise) { + return RPromiseMRForeign.ACCESS; + } else if (obj instanceof RArgsValuesAndNames) { + return RArgsValuesAndNamesMRForeign.ACCESS; + } else if (obj instanceof RLanguage) { + return RLanguageMRForeign.ACCESS; + } else if (obj instanceof ActiveBinding) { + return ActiveBindingMRForeign.ACCESS; - @TruffleBoundary - private static ForeignAccess createForeignAccess(Class<? extends RTruffleObject> clazz) { - ForeignAccess foreignAccess = null; - String name = clazz.getSimpleName(); - if (RNull.class.isAssignableFrom(clazz)) { - foreignAccess = RNullMRForeign.createAccess(); - } else if (RList.class.isAssignableFrom(clazz)) { - foreignAccess = RListMRForeign.createAccess(); - } else if (REnvironment.class.isAssignableFrom(clazz)) { - foreignAccess = REnvironmentMRForeign.createAccess(); - } else if (RPairList.class.isAssignableFrom(clazz)) { - foreignAccess = RPairListMRForeign.createAccess(); - } else if (RFunction.class.isAssignableFrom(clazz)) { - foreignAccess = RFunctionMRForeign.createAccess(); - } else if (DLL.DLLInfo.class.isAssignableFrom(clazz)) { - foreignAccess = DLLInfoMRForeign.createAccess(); - } else if (DLL.DotSymbol.class.isAssignableFrom(clazz)) { - foreignAccess = DLLDotSymbolMRForeign.createAccess(); - } else if (RSymbol.class.isAssignableFrom(clazz)) { - foreignAccess = RSymbolMRForeign.createAccess(); - } else if (RExternalPtr.class.isAssignableFrom(clazz)) { - foreignAccess = RExternalPtrMRForeign.createAccess(); - } else if (RUnboundValue.class.isAssignableFrom(clazz)) { - foreignAccess = RUnboundValueMRForeign.createAccess(); - } else if (NativeRawArray.class.isAssignableFrom(clazz)) { - foreignAccess = NativeRawArrayMRForeign.createAccess(); - } else if (NativeLogicalArray.class.isAssignableFrom(clazz)) { - foreignAccess = NativeLogicalArrayMRForeign.createAccess(); - } else if (NativeCharArray.class.isAssignableFrom(clazz)) { - foreignAccess = NativeCharArrayMRForeign.createAccess(); - } else if (NativeDoubleArray.class.isAssignableFrom(clazz)) { - foreignAccess = NativeDoubleArrayMRForeign.createAccess(); - } else if (NativeIntegerArray.class.isAssignableFrom(clazz)) { - foreignAccess = NativeIntegerArrayMRForeign.createAccess(); - } else if (RInteger.class.isAssignableFrom(clazz)) { - foreignAccess = RIntegerMRForeign.createAccess(); - } else if (RDouble.class.isAssignableFrom(clazz)) { - foreignAccess = RDoubleMRForeign.createAccess(); - } else if (CharSXPWrapper.class.isAssignableFrom(clazz)) { - foreignAccess = CharSXPWrapperMRForeign.createAccess(); } else { - if (RAbstractVector.class.isAssignableFrom(clazz)) { - foreignAccess = ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory()); + if (obj instanceof RAbstractVector) { + return ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory()); } else { - throw RInternalError.unimplemented("foreignAccess: " + name); + throw RInternalError.unimplemented("missing foreign access factory for " + obj.getClass().getSimpleName()); } } - return foreignAccess; - } - @Override - public ForeignAccess getForeignAccess(RTruffleObject obj) { - CompilerAsserts.neverPartOfCompilation("getForeignAccess"); - return get(obj); } @Override diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java index 8001e760664966b084c5d2bf830e1bbef491ca2d..c0e648cc3a7eab50e1c93e2f4f8584c45976d514 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java @@ -41,6 +41,8 @@ import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.context.RContext.RCloseable; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; +import com.oracle.truffle.r.runtime.env.frame.RFrameSlot; @MessageResolution(receiverType = RFunction.class, language = TruffleRLanguage.class) public class RFunctionMR { @@ -53,9 +55,13 @@ public class RFunctionMR { @Resolve(message = "EXECUTE") public abstract static class RFunctionExecuteNode extends Node { - private static final FrameDescriptor emptyFrameDescriptor = new FrameDescriptor("R interop frame"); - private final Object argsIdentifier = new Object(); - private final FrameSlot slot = emptyFrameDescriptor.addFrameSlot(argsIdentifier, FrameSlotKind.Object); + private static final FrameDescriptor emptyFrameDescriptor = FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("<interop>", new FrameDescriptor("R interop frame")); + private static final RFrameSlot argsIdentifier = RFrameSlot.createTemp(false); + private static final FrameSlot slot = FrameSlotChangeMonitor.findOrAddFrameSlot(emptyFrameDescriptor, argsIdentifier, FrameSlotKind.Object); + + static { + FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("<function>", emptyFrameDescriptor); + } @Child private RCallBaseNode call = RCallNode.createExplicitCall(argsIdentifier); @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode(); @@ -67,12 +73,10 @@ public class RFunctionMR { RArgsValuesAndNames actualArgs = new RArgsValuesAndNames(arguments, ArgumentsSignature.empty(arguments.length)); try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) { - try { - dummyFrame.setObject(slot, actualArgs); - return call.execute(dummyFrame, receiver); - } finally { - dummyFrame.setObject(slot, null); - } + FrameSlotChangeMonitor.setObject(dummyFrame, slot, actualArgs); + return call.execute(dummyFrame, receiver); + } finally { + FrameSlotChangeMonitor.setObject(dummyFrame, slot, null); } } } diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java new file mode 100644 index 0000000000000000000000000000000000000000..df173b4679df75f8006d1aa34359ebe164b3b40a --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java @@ -0,0 +1,112 @@ +/* + * 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.frame.VirtualFrame; +import com.oracle.truffle.api.interop.CanResolve; +import com.oracle.truffle.api.interop.Message; +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.interop.UnsupportedMessageException; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.engine.TruffleRLanguage; +import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; +import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.context.RContext.RCloseable; +import com.oracle.truffle.r.runtime.data.RLanguage; +import com.oracle.truffle.r.runtime.data.RLogical; +import com.oracle.truffle.r.runtime.data.RNull; + +@MessageResolution(receiverType = RLanguage.class, language = TruffleRLanguage.class) +public class RLanguageMR { + + @Resolve(message = "IS_BOXED") + public abstract static class RLanguageIsBoxedNode extends Node { + protected Object access(@SuppressWarnings("unused") RLanguage receiver) { + return false; + } + } + + @Resolve(message = "HAS_SIZE") + public abstract static class RLanguageHasSizeNode extends Node { + protected Object access(@SuppressWarnings("unused") RLanguage receiver) { + return true; + } + } + + @Resolve(message = "IS_NULL") + public abstract static class RLanguageIsNullNode extends Node { + protected Object access(@SuppressWarnings("unused") RLanguage receiver) { + return false; + } + } + + @Resolve(message = "READ") + public abstract static class RLanguageReadNode extends Node { + @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode(); + + @SuppressWarnings("try") + protected Object access(VirtualFrame frame, RLanguage receiver, int label) { + try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) { + return extract.apply(frame, receiver, new Object[]{label + 1}, RLogical.TRUE, RLogical.TRUE); + } + } + } + + @Resolve(message = "WRITE") + public abstract static class RLanguageWriteNode extends Node { + + @SuppressWarnings("unused") + protected Object access(VirtualFrame frame, RLanguage receiver, int label, Object valueObj) { + throw UnsupportedMessageException.raise(Message.WRITE); + } + } + + @Resolve(message = "KEYS") + public abstract static class RLanguageKeysNode extends Node { + + protected Object access(@SuppressWarnings("unused") RLanguage receiver) { + return RNull.instance; + } + } + + @Resolve(message = "KEY_INFO") + public abstract static class RLanguageKeyInfoNode extends Node { + + @SuppressWarnings("unused") + protected Object access(VirtualFrame frame, RLanguage receiver, String identifier) { + return 0; + } + } + + @CanResolve + public abstract static class RLanguageCheck extends Node { + + protected static boolean test(TruffleObject receiver) { + return receiver instanceof RLanguage; + } + } +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java index be2017c3720fd630b50e3a9a8e8394c019fa9a4a..c202c4896041792a89c35d2c7ed62b7e7f20e7da 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java @@ -22,21 +22,27 @@ */ package com.oracle.truffle.r.engine.interop; +import static com.oracle.truffle.r.engine.interop.Utils.javaToRPrimitive; + +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.frame.VirtualFrame; 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.ConditionProfile; import com.oracle.truffle.r.engine.TruffleRLanguage; import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode; import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; -import com.oracle.truffle.r.runtime.RRuntime; 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.RNull; +import com.oracle.truffle.r.runtime.data.RStringVector; @MessageResolution(receiverType = RList.class, language = TruffleRLanguage.class) public class RListMR { @@ -77,28 +83,14 @@ public class RListMR { @Resolve(message = "WRITE") public abstract static class RListWriteNode extends Node { - @Child private ReplaceVectorNode extract = ReplaceVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + @Child private ReplaceVectorNode replace = ReplaceVectorNode.create(ElementAccessMode.SUBSCRIPT, true); @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode(); @SuppressWarnings("try") protected Object access(VirtualFrame frame, RList receiver, String field, Object valueObj) { try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) { - Object value = valueObj; - if (value instanceof Short) { - value = (int) ((Short) value).shortValue(); - } else if (value instanceof Float) { - float floatValue = ((Float) value).floatValue(); - value = new Double(floatValue); - } else if (value instanceof Boolean) { - boolean booleanValue = ((Boolean) value).booleanValue(); - value = booleanValue ? RRuntime.LOGICAL_TRUE : RRuntime.LOGICAL_FALSE; - } else if (value instanceof Character) { - value = (int) ((Character) value).charValue(); - } else if (value instanceof Byte) { - value = (int) ((Byte) value).byteValue(); - } - Object x = extract.apply(frame, receiver, new Object[]{field}, value); - return x; + Object value = javaToRPrimitive(valueObj); + return replace.apply(frame, receiver, new Object[]{field}, value); } } } @@ -111,7 +103,50 @@ public class RListMR { @SuppressWarnings("try") protected Object access(RList receiver) { try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) { - return getNamesNode.getNames(receiver); + RStringVector names = getNamesNode.getNames(receiver); + return names != null ? names : RNull.instance; + } + } + } + + @Resolve(message = "KEY_INFO") + public abstract static class RListKeyInfoNode extends Node { + @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode(); + @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create(); + @Child private ExtractVectorNode extractNode; + + private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile(); + + private static final int READABLE = 1 << 1; + private static final int WRITABLE = 1 << 2; + private static final int INVOCABLE = 1 << 3; + private static final int INTERNAL = 1 << 4; + + @SuppressWarnings("try") + protected Object access(VirtualFrame frame, RList receiver, String identifier) { + try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) { + int info = 0; + RStringVector names = getNamesNode.getNames(receiver); + for (int i = 0; i < names.getLength(); i++) { + if (identifier.equals(names.getDataAt(i))) { + info = 1; + break; + } + } + if (unknownIdentifier.profile(info == 0)) { + return info; + } + + info = info + READABLE + WRITABLE; + if (extractNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + extractNode = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true)); + } + Object value = extractNode.applyAccessField(frame, receiver, identifier); + if (value instanceof RFunction) { + info = info + INVOCABLE; + } + return info; } } } diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RNullMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RNullMR.java index be1ae97f401b4cccd3808ec0589258dfe4ac4298..4fa755eacc68df01dd1bf4a5989e5431245c27d8 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RNullMR.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RNullMR.java @@ -32,6 +32,11 @@ import com.oracle.truffle.r.runtime.data.RNull; @MessageResolution(receiverType = RNull.class, language = TruffleRLanguage.class) public class RNullMR { + /** + * Workaround to avoid NFI converting {@link RNull} to {@code null}. + */ + private static boolean isNull = true; + @Resolve(message = "IS_BOXED") public abstract static class RNullIsBoxedNode extends Node { protected Object access(@SuppressWarnings("unused") RNull receiver) { @@ -49,7 +54,7 @@ public class RNullMR { @Resolve(message = "IS_NULL") public abstract static class RNullIsNullNode extends Node { protected Object access(@SuppressWarnings("unused") RNull receiver) { - return true; + return isNull; } } @@ -60,4 +65,10 @@ public class RNullMR { return receiver instanceof RNull; } } + + public static boolean setIsNull(boolean value) { + boolean prev = isNull; + isNull = value; + return prev; + } } diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java new file mode 100644 index 0000000000000000000000000000000000000000..257848ba0269263f98cacc9a04064c19f48d519a --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java @@ -0,0 +1,70 @@ +/* + * 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.RPromise; + +@MessageResolution(receiverType = RPromise.class, language = TruffleRLanguage.class) +public class RPromiseMR { + @Resolve(message = "IS_BOXED") + public abstract static class RPromiseIsBoxedNode extends Node { + protected Object access(@SuppressWarnings("unused") RPromise receiver) { + return true; + } + } + + @Resolve(message = "HAS_SIZE") + public abstract static class RPromiseHasSizeNode extends Node { + protected Object access(@SuppressWarnings("unused") RPromise receiver) { + return false; + } + } + + @Resolve(message = "IS_NULL") + public abstract static class RPromiseIsNullNode extends Node { + protected Object access(@SuppressWarnings("unused") RPromise receiver) { + return false; + } + } + + @Resolve(message = "UNBOX") + public abstract static class RPromiseUnboxNode extends Node { + protected Object access(RPromise receiver) { + return receiver.getValue(); + } + } + + @CanResolve + public abstract static class RPromiseCheck extends Node { + + protected static boolean test(TruffleObject receiver) { + return receiver instanceof RPromise; + } + } +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RS4ObjectMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RS4ObjectMR.java new file mode 100644 index 0000000000000000000000000000000000000000..0c62ef582b8ca097738e8e1e891a13128d91b947 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RS4ObjectMR.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2017, 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.frame.VirtualFrame; +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.nodes.attributes.ArrayAttributeNode; +import com.oracle.truffle.r.nodes.attributes.GetAttributeNode; +import com.oracle.truffle.r.nodes.attributes.SetAttributeNode; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.context.RContext.RCloseable; +import com.oracle.truffle.r.runtime.data.RAttributesLayout.RAttribute; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RS4Object; + +@MessageResolution(receiverType = RS4Object.class, language = TruffleRLanguage.class) +public class RS4ObjectMR { + + @Resolve(message = "IS_BOXED") + public abstract static class RS4ObjectIsBoxedNode extends Node { + protected Object access(@SuppressWarnings("unused") RS4Object receiver) { + return false; + } + } + + @Resolve(message = "HAS_SIZE") + public abstract static class RS4ObjectHasSizeNode extends Node { + protected Object access(@SuppressWarnings("unused") RS4Object receiver) { + return false; + } + } + + @Resolve(message = "IS_NULL") + public abstract static class RS4ObjectIsNullNode extends Node { + protected Object access(@SuppressWarnings("unused") RS4Object receiver) { + return false; + } + } + + @Resolve(message = "READ") + public abstract static class RS4ObjectReadNode extends Node { + @Child private GetAttributeNode getAttributeNode = GetAttributeNode.create(); + @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode(); + + @SuppressWarnings("try") + protected Object access(VirtualFrame frame, RS4Object receiver, String field) { + try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) { + return getAttributeNode.execute(receiver, field); + } + } + } + + @Resolve(message = "WRITE") + public abstract static class RS4ObjectWriteNode extends Node { + @Child private SetAttributeNode setAttributeNode = SetAttributeNode.create(); + @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode(); + + @SuppressWarnings("try") + protected Object access(VirtualFrame frame, RS4Object receiver, String field, Object valueObj) { + try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) { + Object value = Utils.javaToRPrimitive(valueObj); + setAttributeNode.execute(receiver, field, value); + return value; + } + } + } + + @Resolve(message = "KEYS") + public abstract static class RS4ObjectKeysNode extends Node { + @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode(); + @Child private ArrayAttributeNode arrayAttrAccess = ArrayAttributeNode.create(); + + @SuppressWarnings("try") + protected Object access(RS4Object receiver) { + try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) { + RAttribute[] attributes = arrayAttrAccess.execute(receiver.getAttributes()); + String[] data = new String[attributes.length]; + for (int i = 0; i < data.length; i++) { + data[i] = attributes[i].getName(); + } + return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR); + } + } + } + + @CanResolve + public abstract static class RS4ObjectCheck extends Node { + protected static boolean test(TruffleObject receiver) { + return receiver instanceof RS4Object; + } + } +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/SetResultImplMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/SetResultImplMR.java new file mode 100644 index 0000000000000000000000000000000000000000..69cf41035975ae5e192aa05979df3225a1e74749 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/SetResultImplMR.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017, 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.frame.VirtualFrame; +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.engine.interop.ffi.nfi.TruffleNFI_Base; + +@MessageResolution(receiverType = TruffleNFI_Base.TruffleNFI_ReadlinkNode.SetResultImpl.class, language = TruffleRLanguage.class) +public class SetResultImplMR { + @CanResolve + public abstract static class SetResultImplCheck extends Node { + + protected static boolean test(TruffleObject receiver) { + return receiver instanceof TruffleNFI_Base.TruffleNFI_ReadlinkNode.SetResultImpl; + } + } + + @Resolve(message = "EXECUTE") + public abstract static class SetResultImplExecute extends Node { + protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_Base.TruffleNFI_ReadlinkNode.SetResultImpl receiver, Object[] arguments) { + receiver.setResult((String) arguments[0], (int) arguments[1]); + return receiver; + } + } +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnameUpCallImplMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnameUpCallImplMR.java new file mode 100644 index 0000000000000000000000000000000000000000..6382443b4fd3d6aec17eba4afd4cd3e1b9ed9316 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnameUpCallImplMR.java @@ -0,0 +1,52 @@ +/* + * 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 + * 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.frame.VirtualFrame; +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.engine.interop.ffi.nfi.TruffleNFI_Base; + +@MessageResolution(receiverType = TruffleNFI_Base.TruffleNFI_UnameNode.UnameUpCallImpl.class, language = TruffleRLanguage.class) +public class UnameUpCallImplMR { + @CanResolve + public abstract static class UnameUpCallImplCheck extends Node { + + protected static boolean test(TruffleObject receiver) { + return receiver instanceof TruffleNFI_Base.TruffleNFI_UnameNode.UnameUpCallImpl; + } + } + + @Resolve(message = "EXECUTE") + public abstract static class UnameUpCallImplExecute extends Node { + protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_Base.TruffleNFI_UnameNode.UnameUpCallImpl receiver, Object[] arguments) { + receiver.unameUpCall((String) arguments[0], (String) arguments[1], (String) arguments[2], (String) arguments[3], (String) arguments[4]); + return receiver; + } + } + +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnsafeAdapter.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnsafeAdapter.java index 1306e9bc7c547df11ce4f730b10e23749e689518..7ef0df76f752eda1c64afcae8f588763f148d80c 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnsafeAdapter.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnsafeAdapter.java @@ -26,8 +26,8 @@ import java.lang.reflect.Field; import sun.misc.Unsafe; -class UnsafeAdapter { - static final Unsafe UNSAFE = initUnsafe(); +public class UnsafeAdapter { + public static final Unsafe UNSAFE = initUnsafe(); private static Unsafe initUnsafe() { try { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToStringVectorClosure.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/Utils.java similarity index 54% rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToStringVectorClosure.java rename to com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/Utils.java index 6a7ce849bbba683617452959e842f43d5c849f60..6d044539546c64e6d2b97ca0d994e6c2db852bc1 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToStringVectorClosure.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/Utils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -20,26 +20,26 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.data.closures; +package com.oracle.truffle.r.engine.interop; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -final class RDoubleToStringVectorClosure extends RToStringVectorClosure implements RAbstractStringVector { - - RDoubleToStringVectorClosure(RAbstractDoubleVector vector) { - super(vector); - } - - @Override - public String getDataAt(int index) { - double data = ((RAbstractDoubleVector) vector).getDataAt(index); - if (!vector.isComplete() && RRuntime.isNA(data)) { - return RRuntime.STRING_NA; - } else { - return RContext.getRRuntimeASTAccess().encodeDouble(data); +class Utils { + static Object javaToRPrimitive(Object valueObj) { + Object value = valueObj; + if (value instanceof Short) { + value = (int) ((Short) value).shortValue(); + } else if (value instanceof Float) { + float floatValue = ((Float) value).floatValue(); + value = new Double(floatValue); + } else if (value instanceof Boolean) { + boolean booleanValue = ((Boolean) value).booleanValue(); + value = booleanValue ? RRuntime.LOGICAL_TRUE : RRuntime.LOGICAL_FALSE; + } else if (value instanceof Character) { + value = (int) ((Character) value).charValue(); + } else if (value instanceof Byte) { + value = (int) ((Byte) value).byteValue(); } + return value; } } diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java new file mode 100644 index 0000000000000000000000000000000000000000..3ad8a7f1da8940084e236abec1033023f40d4d32 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java @@ -0,0 +1,399 @@ +/* + * 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 + * 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.ffi.nfi; + +import java.io.IOException; +import java.util.ArrayList; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.InteropException; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.java.JavaInterop; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.data.RTruffleObject; +import com.oracle.truffle.r.runtime.ffi.BaseRFFI; + +public class TruffleNFI_Base implements BaseRFFI { + + private enum Function { + getpid("(): sint32", true), + getcwd("([uint8], sint32): sint32", true), + chdir("(string): sint32", true), + mkdir("(string, sint32): sint32", true), + call_readlink("((string, sint32): void, string): void", false), + mkdtemp("([uint8]): sint32", true), + chmod("(string, sint32): sint32", true), + call_strtol("((sint64, sint32): void, string, sint32): void", false), + call_uname("((string, string, string, string, string): void): void", false), + call_glob("(string, (string): void): void", false); + + private final int argCount; + private final String signature; + private final boolean useDefaultLibrary; + private Node message; + private TruffleObject function; + + Function() { + this(null, true); + } + + Function(String signature, boolean useDefaultLibrary) { + this.argCount = TruffleNFI_Utils.getArgCount(signature); + this.signature = signature; + this.useDefaultLibrary = useDefaultLibrary; + } + + private void initialize() { + if (message == null) { + message = Message.createExecute(argCount).createNode(); + } + if (function == null) { + function = TruffleNFI_Utils.lookupAndBind(name(), useDefaultLibrary, signature); + } + } + } + + public static class TruffleNFI_GetpidNode extends GetpidNode { + @Override + public int execute() { + Function.getpid.initialize(); + try { + int result = (int) ForeignAccess.sendExecute(Function.getpid.message, Function.getpid.function); + return result; + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + + } + } + + public static class TruffleNFI_GetwdNode extends GetwdNode { + @TruffleBoundary + @Override + public String execute() { + byte[] buf = new byte[4096]; + Function.getcwd.initialize(); + try { + int result = (int) ForeignAccess.sendExecute(Function.getcwd.message, Function.getcwd.function, JavaInterop.asTruffleObject(buf), buf.length); + if (result == 0) { + return null; + } else { + int i = 0; + while (buf[i] != 0 && i < buf.length) { + i++; + } + return new String(buf, 0, i); + } + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + public static class TruffleNFI_SetwdNode extends SetwdNode { + @Override + public int execute(String dir) { + Function.chdir.initialize(); + try { + int result = (int) ForeignAccess.sendExecute(Function.chdir.message, Function.chdir.function, dir); + return result; + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + public static class TruffleNFI_MkdirNode extends MkdirNode { + @Override + public void execute(String dir, int mode) throws IOException { + Function.mkdir.initialize(); + try { + int result = (int) ForeignAccess.sendExecute(Function.mkdir.message, Function.mkdir.function, dir, mode); + if (result != 0) { + throw new IOException("mkdir " + dir + " failed"); + } + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + public static class TruffleNFI_ReadlinkNode extends ReadlinkNode { + private static final int EINVAL = 22; + + interface SetResult { + void setResult(String link, int errno); + } + + public static class SetResultImpl implements SetResult, RTruffleObject { + private String link; + private int errno; + + @Override + public void setResult(String link, int errno) { + this.link = link; + this.errno = errno; + } + + } + + @Override + public String execute(String path) throws IOException { + Function.call_readlink.initialize(); + try { + SetResultImpl setResultImpl = new SetResultImpl(); + ForeignAccess.sendExecute(Function.call_readlink.message, Function.call_readlink.function, setResultImpl, path); + if (setResultImpl.link == null) { + if (setResultImpl.errno == EINVAL) { + return path; + } else { + // some other error + throw new IOException("readlink failed: " + setResultImpl.errno); + } + } + return setResultImpl.link; + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + public static class TruffleNFI_MkdtempNode extends MkdtempNode { + @TruffleBoundary + @Override + public String execute(String template) { + /* + * Not only must the (C) string end in XXXXXX it must also be null-terminated. Since it + * is modified by mkdtemp we must make a copy. + */ + byte[] bytes = template.getBytes(); + byte[] ztbytes = new byte[bytes.length + 1]; + System.arraycopy(bytes, 0, ztbytes, 0, bytes.length); + ztbytes[bytes.length] = 0; + Function.mkdtemp.initialize(); + try { + int result = (int) ForeignAccess.sendExecute(Function.mkdtemp.message, Function.mkdtemp.function, JavaInterop.asTruffleObject(ztbytes)); + if (result == 0) { + return null; + } else { + return new String(ztbytes, 0, bytes.length); + } + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + public static class TruffleNFI_ChmodNode extends ChmodNode { + @Override + public int execute(String path, int mode) { + Function.chmod.initialize(); + try { + int result = (int) ForeignAccess.sendExecute(Function.chmod.message, Function.chmod.function, path, mode); + return result; + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + public static class TruffleNFI_StrolNode extends StrolNode { + interface SetResult { + void setResult(long result, int errno); + } + + private static class SetResultImpl implements SetResult { + private long result; + private int errno; + + @Override + public void setResult(long result, int errno) { + this.result = result; + this.errno = errno; + } + } + + @Override + public long execute(String s, int base) throws IllegalArgumentException { + Function.call_strtol.initialize(); + try { + SetResultImpl setResultImpl = new SetResultImpl(); + ForeignAccess.sendExecute(Function.call_strtol.message, Function.call_strtol.function, JavaInterop.asTruffleFunction(SetResult.class, setResultImpl), s, base); + if (setResultImpl.errno != 0) { + throw new IllegalArgumentException("strtol failure"); + } else { + return setResultImpl.result; + } + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + public static class TruffleNFI_UnameNode extends UnameNode { + private static UnameUpCallImpl unameUpCallImpl; + + private interface UnameUpCall { + void unameUpCall(String sysname, String release, String version, String machine, String nodename); + } + + public static class UnameUpCallImpl implements UnameUpCall, UtsName, RTruffleObject { + private String sysname; + private String release; + private String version; + private String machine; + private String nodename; + + @Override + public void unameUpCall(String sysnameA, String releaseA, String versionA, String machineA, String nodenameA) { + sysname = sysnameA; + release = releaseA; + version = versionA; + machine = machineA; + nodename = nodenameA; + } + + @Override + public String sysname() { + return sysname; + } + + @Override + public String release() { + return release; + } + + @Override + public String version() { + return version; + } + + @Override + public String machine() { + return machine; + } + + @Override + public String nodename() { + return nodename; + } + + } + + @Override + public UtsName execute() { + Function.call_uname.initialize(); + if (unameUpCallImpl == null) { + unameUpCallImpl = new UnameUpCallImpl(); + try { + ForeignAccess.sendExecute(Function.call_uname.message, Function.call_uname.function, unameUpCallImpl); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + return unameUpCallImpl; + } + } + + public static class TruffleNFI_GlobNode extends GlobNode { + private interface GlobUpCall { + void addPath(String path); + } + + public static class GlobUpCallImpl implements GlobUpCall, RTruffleObject { + private ArrayList<String> paths = new ArrayList<>(); + + @Override + public void addPath(String path) { + paths.add(path); + } + } + + @Override + public ArrayList<String> glob(String pattern) { + Function.call_glob.initialize(); + GlobUpCallImpl globUpCallImpl = new GlobUpCallImpl(); + try { + ForeignAccess.sendExecute(Function.call_glob.message, Function.call_glob.function, pattern, globUpCallImpl); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + return globUpCallImpl.paths; + } + + } + + @Override + public GetpidNode createGetpidNode() { + return new TruffleNFI_GetpidNode(); + } + + @Override + public GetwdNode createGetwdNode() { + return new TruffleNFI_GetwdNode(); + } + + @Override + public SetwdNode createSetwdNode() { + return new TruffleNFI_SetwdNode(); + } + + @Override + public MkdirNode createMkdirNode() { + return new TruffleNFI_MkdirNode(); + } + + @Override + public ReadlinkNode createReadlinkNode() { + return new TruffleNFI_ReadlinkNode(); + } + + @Override + public MkdtempNode createMkdtempNode() { + return new TruffleNFI_MkdtempNode(); + } + + @Override + public ChmodNode createChmodNode() { + return new TruffleNFI_ChmodNode(); + } + + @Override + public StrolNode createStrolNode() { + return new TruffleNFI_StrolNode(); + } + + @Override + public UnameNode createUnameNode() { + return new TruffleNFI_UnameNode(); + } + + @Override + public GlobNode createGlobNode() { + return new TruffleNFI_GlobNode(); + } + +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_C.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_C.java new file mode 100644 index 0000000000000000000000000000000000000000..dbb6ece117d9ea866e4f85229fe517678b073a94 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_C.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017, 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.ffi.nfi; + +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.InteropException; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_CFactory.TruffleNFI_InvokeCNodeGen; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.ffi.CRFFI; +import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; + +public class TruffleNFI_C implements CRFFI { + public abstract static class TruffleNFI_InvokeCNode extends InvokeCNode { + + @Child Node bindNode = Message.createInvoke(1).createNode(); + + @Specialization(guards = "args.length == 0") + protected void invokeCall0(NativeCallInfo nativeCallInfo, @SuppressWarnings("unused") Object[] args, + @Cached("createExecute(args.length)") Node executeNode) { + synchronized (TruffleNFI_Call.class) { + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(): object"); + ForeignAccess.sendExecute(executeNode, callFunction); + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } + } + } + + public static Node createExecute(int n) { + return Message.createExecute(n).createNode(); + } + + } + + @Override + public InvokeCNode createInvokeCNode() { + return TruffleNFI_InvokeCNodeGen.create(); + } +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_CAccess.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_CAccess.java new file mode 100644 index 0000000000000000000000000000000000000000..a01fd2b14c353d479f6fad1ec6682c099694a080 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_CAccess.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017, 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.ffi.nfi; + +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.InteropException; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.ffi.DLL; +import com.oracle.truffle.r.runtime.ffi.DLLRFFI; +import com.oracle.truffle.r.runtime.ffi.LibPaths; + +public class TruffleNFI_CAccess { + private static TruffleNFI_DLL.NFIHandle handle; + + public enum Function { + READ_POINTER_INT("(pointer): sint32"), + READ_ARRAY_INT("(pointer, sint64): sint32"), + READ_POINTER_DOUBLE("(pointer): double"), + READ_ARRAY_DOUBLE("(pointer, sint32): double"); + + private TruffleObject symbolFunction; + private final String signature; + + Function(String signature) { + this.signature = signature; + + } + + public TruffleObject getSymbolFunction() { + if (handle == null) { + handle = (TruffleNFI_DLL.NFIHandle) DLLRFFI.DLOpenRootNode.create().getCallTarget().call(LibPaths.getBuiltinLibPath("caccess"), true, true); + } + if (symbolFunction == null) { + DLL.SymbolHandle symbolHandle = (DLL.SymbolHandle) DLLRFFI.DLSymRootNode.create().getCallTarget().call(handle, cName()); + assert symbolHandle != null; + Node bind = Message.createInvoke(1).createNode(); + try { + symbolFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", signature); + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } + + } + return symbolFunction; + } + + public String cName() { + return "caccess_" + name().toLowerCase(); + } + } + +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java new file mode 100644 index 0000000000000000000000000000000000000000..85f48b8d1d6c152574a5ab756c6fe8e8d6421956 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java @@ -0,0 +1,479 @@ +/* + * 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 + * 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.ffi.nfi; + +import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCall; +import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCallReturn; +import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceEnabled; + +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.InteropException; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.java.JavaInterop; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.engine.interop.RNullMR; +import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_CallFactory.TruffleNFI_InvokeCallNodeGen; +import com.oracle.truffle.r.nodes.ffi.RFFIUpCallMethod; +import com.oracle.truffle.r.nodes.ffi.RFFIUtils; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.ffi.CallRFFI; +import com.oracle.truffle.r.runtime.ffi.DLL; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; +import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; +import com.oracle.truffle.r.runtime.ffi.RFFIVariables; +import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI; +import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; + +public class TruffleNFI_Call implements CallRFFI { + + private enum INIT_VAR_FUN { + OBJ("(sint32, object) : void"), + DOUBLE("(sint32, double): void"), + STRING("(sint32, string): void"), + INT("(sint32, sint32) : void"); + + private final String funName; + private TruffleObject initFunction; + private final String signature; + + INIT_VAR_FUN(String signature) { + this.signature = signature; + funName = "Call_initvar_" + name().toLowerCase(); + } + } + + /** + * Nesting of native calls is rare but can happen and the cleanup needs to be per call. + */ + private static int callDepth; + + public TruffleNFI_Call() { + initialize(); + TruffleNFI_PkgInit.initialize(); + } + + private static void initVariables() { + Node bind = Message.createInvoke(1).createNode(); + for (INIT_VAR_FUN initVarFun : INIT_VAR_FUN.values()) { + SymbolHandle symbolHandle = DLL.findSymbol(initVarFun.funName, null); // libR + try { + initVarFun.initFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", initVarFun.signature); + } catch (Throwable t) { + throw RInternalError.shouldNotReachHere(t); + } + } + Node executeNode = Message.createExecute(2).createNode(); + RFFIVariables[] variables = RFFIVariables.values(); + for (int i = 0; i < variables.length; i++) { + RFFIVariables var = variables[i]; + Object value = var.getValue(); + if (value == null) { + continue; + } + try { + if (value instanceof Double) { + ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.DOUBLE.initFunction, i, value); + } else if (value instanceof Integer) { + ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.INT.initFunction, i, value); + } else if (value instanceof String) { + ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.STRING.initFunction, i, value); + } else { + ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.OBJ.initFunction, i, value); + } + } catch (Throwable t) { + throw RInternalError.shouldNotReachHere(t); + } + } + } + + private static void initCallbacks(UpCallsRFFI upCallsImpl) { + Node bind = Message.createInvoke(1).createNode(); + Node executeNode = Message.createExecute(1).createNode(); + SymbolHandle symbolHandle = DLL.findSymbol("Rinternals_addCallback", null); + TruffleObject upCallsObject = JavaInterop.asTruffleObject(upCallsImpl); + Node readNode = Message.READ.createNode(); + try { + for (RFFIUpCallMethod upCallMethod : RFFIUpCallMethod.values()) { + Object upCallMethodObject = ForeignAccess.sendRead(readNode, upCallsObject, upCallMethod.name()); + String addCallbackSignature = String.format("(sint32, %s): void", upCallMethod.nfiSignature); + TruffleObject addCallbackFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", addCallbackSignature); + ForeignAccess.sendExecute(executeNode, addCallbackFunction, upCallMethod.ordinal(), upCallMethodObject); + } + } catch (Throwable t) { + throw RInternalError.shouldNotReachHere(t); + } + } + + private enum ReturnArray { + INTEGER_CREATE("([sint32], sint32): uint64", 2), + DOUBLE_CREATE("([double], sint32): uint64", 2), + BYTE_CREATE("([uint8], sint32, sint32): uint64", 3), + INTEGER_EXISTING("(uint64): void", 1), + DOUBLE_EXISTING("(uint64): void", 1), + BYTE_EXISTING("(uint64): void", 1), + FREE("(uint64): void", 1); + + private final String signature; + private final String funName; + private TruffleObject function; + private final Node executeNode; + + ReturnArray(String signature, int numArgs) { + this.signature = signature; + this.funName = "return_" + name(); + this.executeNode = Message.createExecute(numArgs).createNode(); + } + + } + + private static void initReturnArray() { + Node bind = Message.createInvoke(1).createNode(); + for (ReturnArray returnArrayFun : ReturnArray.values()) { + SymbolHandle symbolHandle = DLL.findSymbol(returnArrayFun.funName, null); // libR + try { + returnArrayFun.function = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", returnArrayFun.signature); + } catch (InteropException t) { + throw RInternalError.shouldNotReachHere(t); + } + } + } + + // TODO Nodify? + static long returnArrayCreate(Object array, boolean isString) { + try { + if (array instanceof int[]) { + return (long) ForeignAccess.sendExecute(ReturnArray.INTEGER_CREATE.executeNode, ReturnArray.INTEGER_CREATE.function, JavaInterop.asTruffleObject(array), ((int[]) array).length); + } else if (array instanceof double[]) { + return (long) ForeignAccess.sendExecute(ReturnArray.DOUBLE_CREATE.executeNode, ReturnArray.DOUBLE_CREATE.function, JavaInterop.asTruffleObject(array), ((double[]) array).length); + } else if (array instanceof byte[]) { + return (long) ForeignAccess.sendExecute(ReturnArray.BYTE_CREATE.executeNode, ReturnArray.BYTE_CREATE.function, JavaInterop.asTruffleObject(array), ((byte[]) array).length, + isString ? 1 : 0); + } else { + throw RInternalError.shouldNotReachHere(); + } + } catch (InteropException t) { + throw RInternalError.shouldNotReachHere(t); + } + } + + static void returnArrayExisting(SEXPTYPE type, long address) { + try { + switch (type) { + case INTSXP: + case LGLSXP: + ForeignAccess.sendExecute(ReturnArray.INTEGER_EXISTING.executeNode, ReturnArray.INTEGER_EXISTING.function, address); + break; + case REALSXP: + ForeignAccess.sendExecute(ReturnArray.DOUBLE_EXISTING.executeNode, ReturnArray.DOUBLE_EXISTING.function, address); + break; + case CHARSXP: + case RAWSXP: + ForeignAccess.sendExecute(ReturnArray.BYTE_EXISTING.executeNode, ReturnArray.BYTE_EXISTING.function, address); + break; + default: + throw RInternalError.shouldNotReachHere(); + + } + } catch (InteropException t) { + throw RInternalError.shouldNotReachHere(t); + } + } + + static void freeArray(long address) { + Node executeNode = Message.createExecute(1).createNode(); + try { + ForeignAccess.sendExecute(executeNode, ReturnArray.FREE.function, address); + } catch (InteropException t) { + throw RInternalError.shouldNotReachHere(t); + } + } + + private static void initialize() { + UpCallsRFFI upCallsImpl = RFFIUtils.initialize(new TruffleNFI_UpCallsRFFIImpl()); + if (traceEnabled()) { + traceDownCall("initialize"); + } + try { + initVariables(); + initCallbacks(upCallsImpl); + initReturnArray(); + } finally { + if (traceEnabled()) { + traceDownCallReturn("initialize", null); + } + } + } + + public abstract static class TruffleNFI_InvokeCallNode extends InvokeCallNode { + @Child Node bindNode = Message.createInvoke(1).createNode(); + + @Specialization(guards = "args.length == 0") + protected Object invokeCall0(NativeCallInfo nativeCallInfo, Object[] args, + @Cached("createExecute(args.length)") Node executeNode) { + synchronized (TruffleNFI_Call.class) { + Object result = null; + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(): object"); + result = ForeignAccess.sendExecute(executeNode, callFunction); + return result; + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, result, isNullSetting); + } + } + } + + @Specialization(guards = "args.length == 1") + protected Object invokeCall1(NativeCallInfo nativeCallInfo, Object[] args, + @Cached("createExecute(args.length)") Node executeNode) { + synchronized (TruffleNFI_Call.class) { + Object result = null; + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(object): object"); + result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0])); + return result; + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, result, isNullSetting); + } + } + } + + @Specialization(guards = "args.length == 2") + protected Object invokeCall2(NativeCallInfo nativeCallInfo, Object[] args, + @Cached("createExecute(args.length)") Node executeNode) { + synchronized (TruffleNFI_Call.class) { + Object result = null; + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(object, object): object"); + result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1])); + return result; + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, result, isNullSetting); + } + } + } + + @Specialization(guards = "args.length == 3") + protected Object invokeCall3(NativeCallInfo nativeCallInfo, Object[] args, + @Cached("createExecute(args.length)") Node executeNode) { + synchronized (TruffleNFI_Call.class) { + Object result = null; + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object): object"); + result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]), JavaInterop.asTruffleObject(args[2])); + return result; + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, result, isNullSetting); + } + } + } + + @Specialization(guards = "args.length == 4") + protected Object invokeCall4(NativeCallInfo nativeCallInfo, Object[] args, + @Cached("createExecute(args.length)") Node executeNode) { + synchronized (TruffleNFI_Call.class) { + Object result = null; + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object): object"); + result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]), JavaInterop.asTruffleObject(args[2]), + JavaInterop.asTruffleObject(args[3])); + return result; + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, result, isNullSetting); + } + } + } + + @Specialization(guards = "args.length == 5") + protected Object invokeCall5(NativeCallInfo nativeCallInfo, Object[] args, + @Cached("createExecute(args.length)") Node executeNode) { + synchronized (TruffleNFI_Call.class) { + Object result = null; + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object): object"); + result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]), + JavaInterop.asTruffleObject(args[2]), JavaInterop.asTruffleObject(args[3]), JavaInterop.asTruffleObject(args[4])); + return result; + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, result, isNullSetting); + } + } + } + + @Specialization(guards = "args.length == 6") + protected Object invokeCall6(NativeCallInfo nativeCallInfo, Object[] args, + @Cached("createExecute(args.length)") Node executeNode) { + synchronized (TruffleNFI_Call.class) { + Object result = null; + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object): object"); + result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]), + JavaInterop.asTruffleObject(args[2]), JavaInterop.asTruffleObject(args[3]), JavaInterop.asTruffleObject(args[4]), JavaInterop.asTruffleObject(args[5])); + return result; + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, result, isNullSetting); + } + } + } + + @Specialization(guards = "args.length == 7") + protected Object invokeCall7(NativeCallInfo nativeCallInfo, Object[] args, + @Cached("createExecute(args.length)") Node executeNode) { + synchronized (TruffleNFI_Call.class) { + Object result = null; + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object, object): object"); + result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]), + JavaInterop.asTruffleObject(args[2]), JavaInterop.asTruffleObject(args[3]), JavaInterop.asTruffleObject(args[4]), JavaInterop.asTruffleObject(args[5]), + JavaInterop.asTruffleObject(args[6])); + return result; + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, result, isNullSetting); + } + } + } + + @Specialization(guards = "args.length == 8") + protected Object invokeCall8(NativeCallInfo nativeCallInfo, Object[] args, + @Cached("createExecute(args.length)") Node executeNode) { + synchronized (TruffleNFI_Call.class) { + Object result = null; + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object, object, object): object"); + result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]), + JavaInterop.asTruffleObject(args[2]), JavaInterop.asTruffleObject(args[3]), JavaInterop.asTruffleObject(args[4]), JavaInterop.asTruffleObject(args[5]), + JavaInterop.asTruffleObject(args[6]), JavaInterop.asTruffleObject(args[7])); + return result; + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, result, isNullSetting); + } + } + } + + public static Node createExecute(int n) { + return Message.createExecute(n).createNode(); + } + + } + + public static class TruffleNFI_InvokeVoidCallNode extends InvokeVoidCallNode { + private static final String CallVoid1Sig = "(object): void"; + private static final String CallVoid0Sig = "(): void"; + @Child Node bindNode = Message.createInvoke(1).createNode(); + @Child Node execute0Node = Message.createExecute(0).createNode(); + @Child Node execute1Node = Message.createExecute(1).createNode(); + + @Override + public void execute(NativeCallInfo nativeCallInfo, Object[] args) { + synchronized (TruffleNFI_Call.class) { + boolean isNullSetting = prepareCall(nativeCallInfo.name, args); + try { + switch (args.length) { + case 0: + TruffleObject callVoid0Function = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", CallVoid0Sig); + ForeignAccess.sendExecute(execute0Node, callVoid0Function); + break; + case 1: + TruffleObject callVoid1Function = (TruffleObject) ForeignAccess.sendInvoke(bindNode, + nativeCallInfo.address.asTruffleObject(), "bind", CallVoid1Sig); + ForeignAccess.sendExecute(execute1Node, callVoid1Function, args[0]); + break; + } + } catch (InteropException ex) { + throw RInternalError.shouldNotReachHere(ex); + } finally { + prepareReturn(nativeCallInfo.name, null, isNullSetting); + } + } + } + } + + private static boolean prepareCall(String name, Object[] args) { + if (traceEnabled()) { + traceDownCall(name, args); + } + boolean isNullSetting = RNullMR.setIsNull(false); + TruffleNFI_NativeArray.callEnter(callDepth); + callDepth++; + return isNullSetting; + } + + private static void prepareReturn(String name, Object result, boolean isNullSetting) { + if (traceEnabled()) { + traceDownCallReturn(name, result); + } + TruffleNFI_NativeArray.callEnter(callDepth); + RNullMR.setIsNull(isNullSetting); + callDepth--; + } + + @Override + public InvokeCallNode createInvokeCallNode() { + return TruffleNFI_InvokeCallNodeGen.create(); + } + + @Override + public InvokeVoidCallNode createInvokeVoidCallNode() { + return new TruffleNFI_InvokeVoidCallNode(); + } + +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java new file mode 100644 index 0000000000000000000000000000000000000000..fe390032a4aa5e8877963447e0e3e8a63e3425b8 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2017, 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.ffi.nfi; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.TruffleLanguage.Env; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.InteropException; +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.nodes.Node; +import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.ffi.DLL; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; +import com.oracle.truffle.r.runtime.ffi.DLLRFFI; + +public class TruffleNFI_DLL implements DLLRFFI { + + static class NFIHandle { + @SuppressWarnings("unused") private final String libName; + final TruffleObject libHandle; + + NFIHandle(String libName, TruffleObject libHandle) { + this.libName = libName; + this.libHandle = libHandle; + } + } + + private static class TruffleNFI_DLOpenNode extends DLLRFFI.DLOpenNode { + + @TruffleBoundary + @Override + public Object execute(String path, boolean local, boolean now) { + String libName = DLL.libName(path); + Env env = RContext.getInstance().getEnv(); + TruffleObject libHandle = (TruffleObject) env.parse(Source.newBuilder(prepareLibraryOpen(path, local, now)).name(path).mimeType("application/x-native").build()).call(); + return new NFIHandle(libName, libHandle); + } + } + + @TruffleBoundary + private static String prepareLibraryOpen(String path, boolean local, boolean now) { + StringBuilder sb = new StringBuilder("load"); + sb.append("("); + sb.append(local ? "RTLD_LOCAL" : "RTLD_GLOBAL"); + sb.append('|'); + sb.append(now ? "RTLD_NOW" : "RTLD_LAZY"); + sb.append(")"); + sb.append(' '); + sb.append(path); + return sb.toString(); + } + + private static class TruffleNFI_DLSymNode extends DLLRFFI.DLSymNode { + + @Override + public SymbolHandle execute(Object handle, String symbol) { + assert handle instanceof NFIHandle; + NFIHandle nfiHandle = (NFIHandle) handle; + Node lookupSymbol = Message.READ.createNode(); + try { + TruffleObject result = (TruffleObject) ForeignAccess.sendRead(lookupSymbol, nfiHandle.libHandle, symbol); + return new SymbolHandle(result); + } catch (UnknownIdentifierException e) { + return null; + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(); + } + } + } + + private static class TruffleNFI_DLCloseNode extends DLLRFFI.DLCloseNode { + + @Override + public int execute(Object handle) { + assert handle instanceof NFIHandle; + // TODO + return 0; + } + + } + + @Override + public DLOpenNode createDLOpenNode() { + return new TruffleNFI_DLOpenNode(); + } + + @Override + public DLSymNode createDLSymNode() { + return new TruffleNFI_DLSymNode(); + } + + @Override + public DLCloseNode createDLCloseNode() { + return new TruffleNFI_DLCloseNode(); + } +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Lapack.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Lapack.java new file mode 100644 index 0000000000000000000000000000000000000000..bfb50624dc9b50882c26eec3eb44f518e2fb8b5e --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Lapack.java @@ -0,0 +1,318 @@ +/* + * 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 + * 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.ffi.nfi; + +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.InteropException; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.java.JavaInterop; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.ffi.LapackRFFI; + +public class TruffleNFI_Lapack implements LapackRFFI { + enum Function { + ilaver("([sint32]): void"), + dgeev("(uint8, uint8, sint32, [double], sint32, [double], [double], [double], sint32, [double], sint32, [double], sint32) : sint32"), + dgeqp3("(sint32, sint32, [double], sint32, [sint32], [double], [double], sint32) : sint32"), + dormq("(uint8, uint8, sint32, sint32, sint32, [double], sint32, [double], [double], sint32, [double], sint32) : sint32"), + dtrtrs("(uint8, uint8, uint8, sint32, sint32, [double], sint32, [double], sint32) : sint32"), + dgetrf("(sint32, sint32, [double], sint32, [sint32]) : sint32"), + dpotrf("(uint8, sint32, [double], sint32) : sint32"), + dpotri("(uint8, sint32, [double], sint32) : sint32"), + dpstrf("uint8, sint32, [double], sint32, [sint32], [sint32], double, [double]) : sint32"), + dgesv("(sint32, sint32, [double], sint32, [sint32], [double], sint32) : sint32"), + dlange("(uint8, sint32, sint32, [double], sint32, [double]) : double"), + dgecon("(uint8, sint32, [double], sint32, double, [double], [double], [sint32]) : sint32"), + dsyevr("(uint8, uint8, uint8, sint32, [double], sint32, double, double, sint32, sint32, double, [sint32], [double], [double], sint32, [sint32], [double], sint32, [sint32], sint32) : sint32"); + + private final int argCount; + private final String signature; + @CompilationFinal private Node executeNode; + @CompilationFinal private TruffleObject function; + + Function(String signature) { + this.argCount = TruffleNFI_Utils.getArgCount(signature); + this.signature = signature; + } + + private void initialize() { + if (executeNode == null) { + executeNode = Message.createExecute(argCount).createNode(); + } + if (function == null) { + function = TruffleNFI_Utils.lookupAndBind("call_" + name(), false, signature); + } + } + } + + private static class TruffleNFI_IlaverNode extends IlaverNode { + + @Override + public void execute(int[] version) { + Function.ilaver.initialize(); + try { + ForeignAccess.sendExecute(Function.ilaver.executeNode, Function.ilaver.function, JavaInterop.asTruffleObject(version)); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + + } + } + + private static class TruffleNFI_DgeevNode extends DgeevNode { + + @Override + public int execute(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork) { + Function.dgeev.initialize(); + try { + return (int) ForeignAccess.sendExecute(Function.dgeev.executeNode, Function.dgeev.function, jobVL, jobVR, n, JavaInterop.asTruffleObject(a), lda, + JavaInterop.asTruffleObject(wr), JavaInterop.asTruffleObject(wi), JavaInterop.asTruffleObject(vl), ldvl, + JavaInterop.asTruffleObject(vr), ldvr, JavaInterop.asTruffleObject(work), lwork); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + private static class TruffleNFI_Dgeqp3Node extends Dgeqp3Node { + + @Override + public int execute(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork) { + Function.dgeqp3.initialize(); + try { + return (int) ForeignAccess.sendExecute(Function.dgeqp3.executeNode, Function.dgeqp3.function, m, n, JavaInterop.asTruffleObject(a), lda, JavaInterop.asTruffleObject(jpvt), + JavaInterop.asTruffleObject(tau), JavaInterop.asTruffleObject(work), lwork); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + private static class TruffleNFI_DormqrNode extends DormqrNode { + + @Override + public int execute(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork) { + Function.dormq.initialize(); + try { + return (int) ForeignAccess.sendExecute(Function.dormq.executeNode, Function.dormq.function, side, trans, m, n, k, JavaInterop.asTruffleObject(a), lda, + JavaInterop.asTruffleObject(tau), JavaInterop.asTruffleObject(c), ldc, JavaInterop.asTruffleObject(work), lwork); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + private static class TruffleNFI_DtrtrsNode extends DtrtrsNode { + + @Override + public int execute(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb) { + Function.dtrtrs.initialize(); + try { + return (int) ForeignAccess.sendExecute(Function.dtrtrs.executeNode, Function.dtrtrs.function, uplo, trans, diag, n, nrhs, JavaInterop.asTruffleObject(a), lda, + JavaInterop.asTruffleObject(b), ldb); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + private static class TruffleNFI_DgetrfNode extends DgetrfNode { + + @Override + public int execute(int m, int n, double[] a, int lda, int[] ipiv) { + Function.dgetrf.initialize(); + try { + return (int) ForeignAccess.sendExecute(Function.dgetrf.executeNode, Function.dgetrf.function, m, n, JavaInterop.asTruffleObject(a), lda, JavaInterop.asTruffleObject(ipiv)); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + private static class TruffleNFI_DpotrfNode extends DpotrfNode { + + @Override + public int execute(char uplo, int n, double[] a, int lda) { + Function.dpotrf.initialize(); + try { + return (int) ForeignAccess.sendExecute(Function.dpotrf.executeNode, Function.dpotrf.function, uplo, n, JavaInterop.asTruffleObject(a), lda); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + private static class TruffleNFI_DpotriNode extends DpotriNode { + + @Override + public int execute(char uplo, int n, double[] a, int lda) { + Function.dpotri.initialize(); + try { + return (int) ForeignAccess.sendExecute(Function.dpotri.executeNode, Function.dpotri.function, uplo, n, JavaInterop.asTruffleObject(a), lda); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + private static class TruffleNFI_DpstrfNode extends DpstrfNode { + + @Override + public int execute(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work) { + Function.dpstrf.initialize(); + try { + return (int) ForeignAccess.sendExecute(Function.dpstrf.executeNode, Function.dpstrf.function, uplo, n, JavaInterop.asTruffleObject(a), lda, + JavaInterop.asTruffleObject(piv), JavaInterop.asTruffleObject(rank), tol, JavaInterop.asTruffleObject(work)); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + private static class TruffleNFI_DgesvNode extends DgesvNode { + + @Override + public int execute(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb) { + Function.dgesv.initialize(); + try { + return (int) ForeignAccess.sendExecute(Function.dgesv.executeNode, Function.dgesv.function, n, nrhs, JavaInterop.asTruffleObject(a), lda, JavaInterop.asTruffleObject(ipiv), + JavaInterop.asTruffleObject(b), ldb); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + private static class TruffleNFI_DlangeNode extends DlangeNode { + + @Override + public double execute(char norm, int m, int n, double[] a, int lda, double[] work) { + Function.dlange.initialize(); + try { + return (double) ForeignAccess.sendExecute(Function.dlange.executeNode, Function.dlange.function, norm, m, n, JavaInterop.asTruffleObject(a), lda, + JavaInterop.asTruffleObject(work)); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + private static class TruffleNFI_DgeconNode extends DgeconNode { + + @Override + public int execute(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork) { + Function.dgecon.initialize(); + try { + return (int) ForeignAccess.sendExecute(Function.dgecon.executeNode, Function.dgecon.function, norm, n, JavaInterop.asTruffleObject(a), lda, anorm, JavaInterop.asTruffleObject(rcond), + JavaInterop.asTruffleObject(work), JavaInterop.asTruffleObject(iwork)); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + private static class TruffleNFI_DsyevrNode extends DsyevrNode { + + @Override + public int execute(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, double[] w, double[] z, int ldz, int[] isuppz, + double[] work, int lwork, int[] iwork, int liwork) { + Function.dsyevr.initialize(); + try { + return (int) ForeignAccess.sendExecute(Function.dsyevr.executeNode, Function.dsyevr.function, jobz, range, uplo, n, JavaInterop.asTruffleObject(a), + lda, vl, vu, il, iu, abstol, JavaInterop.asTruffleObject(m), JavaInterop.asTruffleObject(w), JavaInterop.asTruffleObject(z), ldz, + JavaInterop.asTruffleObject(isuppz), JavaInterop.asTruffleObject(work), lwork, JavaInterop.asTruffleObject(iwork), liwork); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + @Override + public IlaverNode createIlaverNode() { + return new TruffleNFI_IlaverNode(); + } + + @Override + public DgeevNode createDgeevNode() { + return new TruffleNFI_DgeevNode(); + } + + @Override + public Dgeqp3Node createDgeqp3Node() { + return new TruffleNFI_Dgeqp3Node(); + } + + @Override + public DormqrNode createDormqrNode() { + return new TruffleNFI_DormqrNode(); + } + + @Override + public DtrtrsNode createDtrtrsNode() { + return new TruffleNFI_DtrtrsNode(); + } + + @Override + public DgetrfNode createDgetrfNode() { + return new TruffleNFI_DgetrfNode(); + } + + @Override + public DpotrfNode createDpotrfNode() { + return new TruffleNFI_DpotrfNode(); + } + + @Override + public DpotriNode createDpotriNode() { + return new TruffleNFI_DpotriNode(); + } + + @Override + public DpstrfNode createDpstrfNode() { + return new TruffleNFI_DpstrfNode(); + } + + @Override + public DgesvNode createDgesvNode() { + return new TruffleNFI_DgesvNode(); + } + + @Override + public DlangeNode createDlangeNode() { + return new TruffleNFI_DlangeNode(); + } + + @Override + public DgeconNode createDgeconNode() { + return new TruffleNFI_DgeconNode(); + } + + @Override + public DsyevrNode createDsyevrNode() { + return new TruffleNFI_DsyevrNode(); + } + +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Misc.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Misc.java new file mode 100644 index 0000000000000000000000000000000000000000..9baa8a501139a8b5267323d2151848e71733c1fa --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Misc.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017, 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.ffi.nfi; + +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.InteropException; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.java.JavaInterop; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.ffi.MiscRFFI; + +public class TruffleNFI_Misc implements MiscRFFI { + + private static class TruffleNFI_ExactSumNode extends ExactSumNode { + @Child Node messageNode = Message.createExecute(4).createNode(); + private TruffleObject function; + + @Override + public double execute(double[] values, boolean hasNa, boolean naRm) { + if (function == null) { + function = TruffleNFI_Utils.lookupAndBind("exactSumFunc", false, "([double], sint32, sint32, sint32): double"); + } + try { + return (double) ForeignAccess.sendExecute(messageNode, function, JavaInterop.asTruffleObject(values), values.length, hasNa ? 1 : 0, naRm ? 1 : 0); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + } + + @Override + public ExactSumNode createExactSumNode() { + return new TruffleNFI_ExactSumNode(); + } + +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_NativeArray.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_NativeArray.java new file mode 100644 index 0000000000000000000000000000000000000000..8a69a8d47b5accd9cc8c0fd8e45bfaa5538a28ff --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_NativeArray.java @@ -0,0 +1,167 @@ +/* + * 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 + * 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.ffi.nfi; + +import java.util.Arrays; + +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; + +/** + * Support for the {@code INTEGER, LOGICAL, ...} functions in the RFFI, which must return the same + * array while an FFI call is in progress. + */ +public class TruffleNFI_NativeArray { + private static int tableHwm; + private static int[] hwmStack = new int[16]; + private static Info[] table = new Info[64]; + + static { + initTableElements(0); + } + + private static class Info { + /** + * E.g., {@link RIntVector}. + */ + Object x; + /** + * internal array, e.g. {@code int[]}. + */ + Object array; + /** + * {@code null} unless {@code x} is an {@link RLogicalVector}, in which case it is the + * underlying {@code byte[]}. + */ + byte[] logicalByteArray; + + long arrayAddress; + } + + private static void initTableElements(int startIndex) { + for (int i = startIndex; i < table.length; i++) { + table[i] = new Info(); + } + } + + static void callEnter(int callDepth) { + hwmStack[callDepth] = tableHwm; + } + + static void callExit(int callDepth) { + int oldHwm = hwmStack[callDepth - 1]; + for (int i = oldHwm; i < tableHwm; i++) { + Info info = table[i]; + if (info.x != null) { + if (info.logicalByteArray != null) { + boolean seenNA = false; + int[] xai = (int[]) info.array; + for (int j = 0; j < xai.length; j++) { + int xaival = xai[j]; + byte xal; + if (xaival == RRuntime.INT_NA) { + seenNA = true; + xal = RRuntime.LOGICAL_NA; + } else { + xal = (byte) xaival; + } + info.logicalByteArray[j] = xal; + } + if (seenNA) { + RLogicalVector lv = (RLogicalVector) info.x; + lv.setComplete(false); + } + } + TruffleNFI_Call.freeArray(info.arrayAddress); + } + } + tableHwm = oldHwm; + } + + /** + * Searches table for an entry matching {@code x}. + * + * @return the associated native array address or {@code 0} if not found. + */ + static long findArray(Object x) { + for (int i = 0; i < tableHwm; i++) { + if (table[i].x == x) { + return table[i].arrayAddress; + } + } + return 0; + } + + /** + * Records that the {@code array} associated with object {@code x} has been requested by the + * native code from, e.g., an {@code INTEGER(x)} function. + * + * @return the native array address + */ + static long recordArray(Object x, Object array, SEXPTYPE type) { + Object xa; + byte[] logicalByteArray = null; + boolean isString = false; + switch (type) { + case INTSXP: + case REALSXP: + case RAWSXP: + case CHARSXP: + isString = type == SEXPTYPE.CHARSXP; + xa = array; + break; + + case LGLSXP: { + byte[] xal = (byte[]) array; + // RFFI wants int* + int[] xai = new int[xal.length]; + for (int i = 0; i < xai.length; i++) { + byte lval = xal[i]; + xai[i] = RRuntime.isNA(lval) ? RRuntime.INT_NA : lval; + } + xa = xai; + logicalByteArray = xal; + break; + } + + default: + throw RInternalError.shouldNotReachHere(); + + } + if (tableHwm == table.length) { + table = Arrays.copyOf(table, table.length * 2); + initTableElements(tableHwm); + } + Info t = table[tableHwm]; + t.x = x; + t.array = xa; + t.logicalByteArray = logicalByteArray; + t.arrayAddress = TruffleNFI_Call.returnArrayCreate(xa, isString); + tableHwm++; + return t.arrayAddress; + } + +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java new file mode 100644 index 0000000000000000000000000000000000000000..50b713e9625588e2f5ef4eff05da7647d9f8f8be --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java @@ -0,0 +1,215 @@ +/* + * 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 + * 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.ffi.nfi; + +import java.nio.charset.StandardCharsets; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.InteropException; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.java.JavaInterop; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.data.RTruffleObject; +import com.oracle.truffle.r.runtime.ffi.PCRERFFI; + +public class TruffleNFI_PCRE implements PCRERFFI { + private enum Function { + maketables("(): sint64", true), + compile("((uint64, string, sint32): void, string, sint32, uint64): void", false), + getcapturecount("(uint64, uint64): sint32", false), + getcapturenames("((sint32, string): void, uint64, uint64): sint32", false), + study("(uint64, sint32): void", false), + exec("(uint64, uint64, [uint8], sint32, sint32, sint32, [sint32], sint32): sint32", true); + + private final int argCount; + private final String signature; + private final String callName; + private Node executeNode; + private TruffleObject function; + + Function(String signature, boolean direct) { + this.argCount = TruffleNFI_Utils.getArgCount(signature); + this.signature = signature; + this.callName = (direct ? "pcre_" : "call_") + name(); + } + + private void initialize() { + if (executeNode == null) { + executeNode = Message.createExecute(argCount).createNode(); + } + if (function == null) { + function = TruffleNFI_Utils.lookupAndBind(callName, false, signature); + } + } + } + + private static class TruffleNFI_MaketablesNode extends MaketablesNode { + + @Override + public long execute() { + Function.maketables.initialize(); + try { + long result = (long) ForeignAccess.sendExecute(Function.maketables.executeNode, Function.maketables.function); + return result; + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + } + + private static class TruffleNFI_GetCaptureCountNode extends GetCaptureCountNode { + + @Override + public int execute(long code, long extra) { + Function.getcapturecount.initialize(); + try { + int result = (int) ForeignAccess.sendExecute(Function.getcapturecount.executeNode, Function.getcapturecount.function, code, extra); + return result; + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + public static class TruffleNFI_GetCaptureNamesNode extends GetCaptureNamesNode { + interface CaptureNames { + void addName(int i, String name); + } + + public static final class CaptureNamesImpl implements CaptureNames, RTruffleObject { + private final String[] captureNames; + + private CaptureNamesImpl(int captureCount) { + captureNames = new String[captureCount]; + } + + @Override + public void addName(int i, String name) { + captureNames[i] = name; + } + + } + + @Override + public String[] execute(long code, long extra, int captureCount) { + Function.getcapturenames.initialize(); + try { + CaptureNamesImpl captureNamesImpl = new CaptureNamesImpl(captureCount); + int result = (int) ForeignAccess.sendExecute(Function.getcapturenames.executeNode, Function.getcapturenames.function, + captureNamesImpl, code, extra); + if (result < 0) { + CompilerDirectives.transferToInterpreter(); + throw RError.error(RError.NO_CALLER, RError.Message.WRONG_PCRE_INFO, result); + } else { + return captureNamesImpl.captureNames; + } + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + } + + public static class TruffleNFI_CompileNode extends CompileNode { + interface MakeResult { + void makeresult(long pcreResult, String errorMessage, int errOffset); + } + + public static class MakeResultImpl implements MakeResult, RTruffleObject { + private PCRERFFI.Result result; + + @Override + public void makeresult(long pcreResult, String errorMessage, int errOffset) { + result = new PCRERFFI.Result(pcreResult, errorMessage, errOffset); + } + } + + @Override + public Result execute(String pattern, int options, long tables) { + Function.compile.initialize(); + try { + MakeResultImpl makeResultImpl = new MakeResultImpl(); + ForeignAccess.sendExecute(Function.compile.executeNode, Function.compile.function, makeResultImpl, + pattern, options, tables); + return makeResultImpl.result; + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + } + + private static class TruffleNFI_ExecNode extends ExecNode { + + @Override + public int execute(long code, long extra, String subject, int offset, int options, int[] ovector) { + Function.exec.initialize(); + try { + + byte[] subjectBytes = subject.getBytes(StandardCharsets.UTF_8); + return (int) ForeignAccess.sendExecute(Function.exec.executeNode, Function.exec.function, code, extra, + JavaInterop.asTruffleObject(subjectBytes), subjectBytes.length, + offset, options, JavaInterop.asTruffleObject(ovector), ovector.length); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + } + + @Override + public MaketablesNode createMaketablesNode() { + return new TruffleNFI_MaketablesNode(); + } + + @Override + public CompileNode createCompileNode() { + return new TruffleNFI_CompileNode(); + } + + @Override + public GetCaptureCountNode createGetCaptureCountNode() { + return new TruffleNFI_GetCaptureCountNode(); + } + + @Override + public GetCaptureNamesNode createGetCaptureNamesNode() { + return new TruffleNFI_GetCaptureNamesNode(); + } + + @Override + public StudyNode createStudyNode() { + throw RInternalError.unimplemented(); + } + + @Override + public ExecNode createExecNode() { + return new TruffleNFI_ExecNode(); + } + +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PkgInit.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PkgInit.java new file mode 100644 index 0000000000000000000000000000000000000000..2621894a9023bdad32f2c628be578698b03a4c4f --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PkgInit.java @@ -0,0 +1,157 @@ +/* + * 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 + * 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.ffi.nfi; + +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.java.JavaInterop; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.ffi.DLL; +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; + +public final class TruffleNFI_PkgInit { + + private enum UpCall { + registerRoutines("(object, sint32, sint32, uint64): void"), + useDynamicSymbols("(object, sint32): sint32"), + setDotSymbolValues("(object, string, pointer, sint32): object"), + forceSymbols("(object, sint32): sint32"); + private final String signature; + + UpCall(String signature) { + this.signature = signature; + } + } + + /** + * The upcalls from native code that support symbol registration. + */ + interface UpCalls { + + /** + * This is the start, called from {@code R_RegisterRoutines}. + * + * @param dllInfo library the symbols are defined in + * @param nstOrd the ordinal value corresponding to + * {@link com.oracle.truffle.r.runtime.ffi.DLL.NativeSymbolType}. + * @param num the number of functions being registered + * @param routines the C address of the function table (not interpreted). + */ + void registerRoutines(DLLInfo dllInfo, int nstOrd, int num, long routines); + + /** + * Internal upcall used by {@code Rdynload_setSymbol}. The {@code fun} value must be + * converted to a {@link TruffleObject} representing the symbol}. + * + * @param dllInfo library the symbol is defined in + * @param name name of function + * @param fun the C address of the function (in the table) + * @param numArgs the number of arguments the function takes. + */ + DotSymbol setDotSymbolValues(DLLInfo dllInfo, String name, TruffleObject fun, int numArgs); + + /** + * Directly implements {@code R_useDynamicSymbols}. + */ + int useDynamicSymbols(DLLInfo dllInfo, int value); + + /** + * Directly implements {@code R_forceSymbols}. + */ + int forceSymbols(DLLInfo dllInfo, int value); + + } + + private static class UpCallsImpl implements UpCalls { + /** + * First create the array, then downcall to native to get the specific info for each symbol + * which is delivered by {@link #setDotSymbolValues}. + */ + @Override + public void registerRoutines(DLLInfo dllInfo, int nstOrd, int num, long routines) { + DotSymbol[] array = new DotSymbol[num]; + for (int i = 0; i < num; i++) { + array[i] = setSymbol(dllInfo, nstOrd, routines, i); + } + dllInfo.setNativeSymbols(nstOrd, array); + } + + @Override + public int useDynamicSymbols(DLLInfo dllInfo, int value) { + return DLL.useDynamicSymbols(dllInfo, value); + } + + @Override + public DotSymbol setDotSymbolValues(DLLInfo dllInfo, String name, TruffleObject fun, int numArgs) { + /* + * We don't know the NFI signature at this point, so we cannot bind the function here. + */ + DotSymbol result = new DotSymbol(name, new SymbolHandle(fun), numArgs); + return result; + } + + @Override + public int forceSymbols(DLLInfo dllInfo, int value) { + return DLL.forceSymbols(dllInfo, value); + } + } + + private static final String SETSYMBOL_SIGNATURE = "(object, sint32, uint64, sint32): object"; + private static TruffleObject setSymbolFunction; + + static void initialize() { + Node bind = Message.createInvoke(1).createNode(); + SymbolHandle symbolHandle = DLL.findSymbol("Rdynload_init", null); + Node executeNode = Message.createExecute(2).createNode(); + UpCallsImpl upCalls = new UpCallsImpl(); + TruffleObject upCallsObject = JavaInterop.asTruffleObject(upCalls); + Node readNode = Message.READ.createNode(); + try { + for (UpCall upCall : UpCall.values()) { + Object upCallMethodObject = ForeignAccess.sendRead(readNode, upCallsObject, upCall.name()); + String addCallbackSignature = String.format("(sint32, %s): void", upCall.signature); + TruffleObject addCallbackFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", addCallbackSignature); + ForeignAccess.sendExecute(executeNode, addCallbackFunction, upCall.ordinal(), upCallMethodObject); + } + symbolHandle = DLL.findSymbol("Rdynload_setSymbol", null); + setSymbolFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", SETSYMBOL_SIGNATURE); + } catch (Throwable t) { + throw RInternalError.shouldNotReachHere(t); + } + } + + private static DotSymbol setSymbol(DLLInfo dllInfo, int nstOrd, long routines, int index) { + Node executeNode = Message.createExecute(4).createNode(); + try { + DotSymbol result = (DotSymbol) ForeignAccess.sendExecute(executeNode, setSymbolFunction, dllInfo, nstOrd, routines, index); + return result; + } catch (Throwable t) { + throw RInternalError.shouldNotReachHere(t); + } + + } +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RAppl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RAppl.java new file mode 100644 index 0000000000000000000000000000000000000000..e0289cdacb3859fe985e575944e9ae99bfb82276 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RAppl.java @@ -0,0 +1,146 @@ +/* + * 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 + * 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.ffi.nfi; + +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.InteropException; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.java.JavaInterop; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.ffi.RApplRFFI; + +public class TruffleNFI_RAppl implements RApplRFFI { + enum Function { + dqrdc2("([double], sint32, sint32, sint32, double, [sint32], [double], [sint32], [double]): void"), + dqrcf("([double], sint32, sint32, [double], [double], sint32, [double], [sint32]): void"), + dqrls("([double], sint32, sint32, [double], sint32, double, [double], [double], [double], [sint32], [sint32], [double], [double]): void"); + + private final int argCount; + private final String signature; + @CompilationFinal private Node executeNode; + @CompilationFinal private TruffleObject function; + + Function(String signature) { + this.argCount = TruffleNFI_Utils.getArgCount(signature); + this.signature = signature; + } + + private void initialize() { + if (executeNode == null) { + executeNode = Message.createExecute(argCount).createNode(); + } + if (function == null) { + function = TruffleNFI_Utils.lookupAndBind("call_" + name(), false, signature); + } + } + } + + private static class TruffleNFI_Dqrdc2Node extends Dqrdc2Node { + + @Override + public void execute(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work) { + Function.dqrdc2.initialize(); + try { + ForeignAccess.sendExecute(Function.dqrdc2.executeNode, Function.dqrdc2.function, + JavaInterop.asTruffleObject(x), + ldx, n, p, tol, + JavaInterop.asTruffleObject(rank), + JavaInterop.asTruffleObject(qraux), + JavaInterop.asTruffleObject(pivot), + JavaInterop.asTruffleObject(work)); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + + } + + } + + private static class TruffleNFI_DqrcfNode extends DqrcfNode { + + @Override + public void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info) { + Function.dqrcf.initialize(); + try { + ForeignAccess.sendExecute(Function.dqrcf.executeNode, Function.dqrcf.function, + JavaInterop.asTruffleObject(x), + n, k, + JavaInterop.asTruffleObject(qraux), + JavaInterop.asTruffleObject(y), + ny, + JavaInterop.asTruffleObject(b), + JavaInterop.asTruffleObject(info)); + + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + } + + private static class TruffleNFI_DqrlsNode extends DqrlsNode { + + @Override + public void execute(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work) { + Function.dqrls.initialize(); + try { + ForeignAccess.sendExecute(Function.dqrls.executeNode, Function.dqrls.function, + JavaInterop.asTruffleObject(x), + n, p, + JavaInterop.asTruffleObject(y), + ny, tol, + JavaInterop.asTruffleObject(b), + JavaInterop.asTruffleObject(rsd), + JavaInterop.asTruffleObject(qty), + JavaInterop.asTruffleObject(k), + JavaInterop.asTruffleObject(jpvt), + JavaInterop.asTruffleObject(qraux), + JavaInterop.asTruffleObject(work)); + + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + + } + + } + + @Override + public Dqrdc2Node createDqrdc2Node() { + return new TruffleNFI_Dqrdc2Node(); + } + + @Override + public DqrcfNode createDqrcfNode() { + return new TruffleNFI_DqrcfNode(); + } + + @Override + public DqrlsNode createDqrlsNode() { + return new TruffleNFI_DqrlsNode(); + } + +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToStringVectorClosure.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_REmbed.java similarity index 56% rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToStringVectorClosure.java rename to com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_REmbed.java index 50cd40a0beac91ff150c9177b6879472d97aa093..798001ff8989ec95277b675732adea59fc3471a3 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToStringVectorClosure.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_REmbed.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -20,25 +20,40 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.data.closures; +package com.oracle.truffle.r.engine.interop.ffi.nfi; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.ffi.REmbedRFFI; -final class RLogicalToStringVectorClosure extends RToStringVectorClosure implements RAbstractStringVector { +public class TruffleNFI_REmbed implements REmbedRFFI { - RLogicalToStringVectorClosure(RAbstractLogicalVector vector) { - super(vector); + @Override + public void suicide(String x) { + throw RInternalError.unimplemented(); + + } + + @Override + public void cleanUp(int type, int x, int y) { + throw RInternalError.unimplemented(); + + } + + @Override + public String readConsole(String prompt) { + throw RInternalError.unimplemented(); } @Override - public String getDataAt(int index) { - byte data = ((RAbstractLogicalVector) vector).getDataAt(index); - if (!vector.isComplete() && RRuntime.isNA(data)) { - return RRuntime.STRING_NA; - } - return RRuntime.logicalToStringNoCheck(data); + public void writeConsole(String x) { + throw RInternalError.unimplemented(); } + + @Override + public void writeErrConsole(String x) { + throw RInternalError.unimplemented(); + + } + } diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..a892fb8876d8fc1524dd660a2db4706d7aef253c --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2017, 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.ffi.nfi; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.context.RContext.ContextState; +import com.oracle.truffle.r.runtime.ffi.BaseRFFI; +import com.oracle.truffle.r.runtime.ffi.CRFFI; +import com.oracle.truffle.r.runtime.ffi.CallRFFI; +import com.oracle.truffle.r.runtime.ffi.DLL; +import com.oracle.truffle.r.runtime.ffi.DLLRFFI; +import com.oracle.truffle.r.runtime.ffi.LapackRFFI; +import com.oracle.truffle.r.runtime.ffi.LibPaths; +import com.oracle.truffle.r.runtime.ffi.MiscRFFI; +import com.oracle.truffle.r.runtime.ffi.PCRERFFI; +import com.oracle.truffle.r.runtime.ffi.RApplRFFI; +import com.oracle.truffle.r.runtime.ffi.REmbedRFFI; +import com.oracle.truffle.r.runtime.ffi.RFFI; +import com.oracle.truffle.r.runtime.ffi.RFFIFactory; +import com.oracle.truffle.r.runtime.ffi.StatsRFFI; +import com.oracle.truffle.r.runtime.ffi.ToolsRFFI; +import com.oracle.truffle.r.runtime.ffi.UserRngRFFI; +import com.oracle.truffle.r.runtime.ffi.ZipRFFI; + +public class TruffleNFI_RFFIFactory extends RFFIFactory implements RFFI { + private static class ContextStateImpl implements RContext.ContextState { + @Override + public ContextState initialize(RContext context) { + if (context.isInitial()) { + String librffiPath = LibPaths.getBuiltinLibPath("R"); + DLL.loadLibR(librffiPath); + } + return this; + } + } + + @Override + public ContextState newContextState() { + return new ContextStateImpl(); + } + + @Override + protected RFFI createRFFI() { + return this; + } + + @CompilationFinal private CRFFI cRFFI; + + @Override + public CRFFI getCRFFI() { + if (cRFFI == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + cRFFI = new TruffleNFI_C(); + } + return cRFFI; + } + + @CompilationFinal private BaseRFFI baseRFFI; + + @Override + public BaseRFFI getBaseRFFI() { + if (baseRFFI == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + baseRFFI = new TruffleNFI_Base(); + } + return baseRFFI; + } + + @CompilationFinal private CallRFFI callRFFI; + + @Override + public CallRFFI getCallRFFI() { + if (callRFFI == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + callRFFI = new TruffleNFI_Call(); + } + return callRFFI; + } + + @CompilationFinal private DLLRFFI dllRFFI; + + @Override + public DLLRFFI getDLLRFFI() { + if (dllRFFI == null) { + dllRFFI = new TruffleNFI_DLL(); + } + return dllRFFI; + } + + @CompilationFinal private UserRngRFFI userRngRFFI; + + @Override + public UserRngRFFI getUserRngRFFI() { + if (userRngRFFI == null) { + userRngRFFI = new TruffleNFI_UserRng(); + } + return userRngRFFI; + } + + @CompilationFinal private ZipRFFI zipRFFI; + + @Override + public ZipRFFI getZipRFFI() { + if (zipRFFI == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + zipRFFI = new TruffleNFI_Zip(); + } + return zipRFFI; + } + + @CompilationFinal private PCRERFFI pcreRFFI; + + @Override + public PCRERFFI getPCRERFFI() { + if (pcreRFFI == null) { + pcreRFFI = new TruffleNFI_PCRE(); + } + return pcreRFFI; + } + + @CompilationFinal private LapackRFFI lapackRFFI; + + @Override + public LapackRFFI getLapackRFFI() { + if (lapackRFFI == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + lapackRFFI = new TruffleNFI_Lapack(); + } + return lapackRFFI; + } + + @CompilationFinal private RApplRFFI rApplRFFI; + + @Override + public RApplRFFI getRApplRFFI() { + if (rApplRFFI == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + rApplRFFI = new TruffleNFI_RAppl(); + } + return rApplRFFI; + } + + @CompilationFinal private StatsRFFI statsRFFI; + + @Override + public StatsRFFI getStatsRFFI() { + if (statsRFFI == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + statsRFFI = new TruffleNFI_Stats(); + } + return statsRFFI; + } + + @CompilationFinal private ToolsRFFI toolsRFFI; + + @Override + public ToolsRFFI getToolsRFFI() { + if (toolsRFFI == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + toolsRFFI = new TruffleNFI_Tools(); + } + return toolsRFFI; + } + + private REmbedRFFI rEmbedRFFI; + + @Override + public REmbedRFFI getREmbedRFFI() { + if (rEmbedRFFI == null) { + rEmbedRFFI = new TruffleNFI_REmbed(); + } + return rEmbedRFFI; + } + + private MiscRFFI miscRFFI; + + @Override + public MiscRFFI getMiscRFFI() { + if (miscRFFI == null) { + miscRFFI = new TruffleNFI_Misc(); + } + return miscRFFI; + } + +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Stats.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Stats.java new file mode 100644 index 0000000000000000000000000000000000000000..f6c8d87e1640ad50158ca3e719616916556b9028 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Stats.java @@ -0,0 +1,108 @@ +/* + * 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 + * 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.ffi.nfi; + +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.InteropException; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.java.JavaInterop; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.ffi.DLL; +import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; +import com.oracle.truffle.r.runtime.ffi.DLLRFFI; +import com.oracle.truffle.r.runtime.ffi.RFFIFactory; +import com.oracle.truffle.r.runtime.ffi.StatsRFFI; + +public class TruffleNFI_Stats implements StatsRFFI { + + private static class TruffleNFI_FactorNode extends FactorNode { + private static final String FFT_FACTOR = "fft_factor"; + private static final String FFT_FACTOR_SIGNATURE = "(sint32, [sint32], [sint32]): void"; + + @Child Node factorMessage = Message.createExecute(3).createNode(); + @Child DLLRFFI.DLSymNode dlsymNode = RFFIFactory.getRFFI().getDLLRFFI().createDLSymNode(); + + @CompilationFinal private TruffleObject fftFactorFunction; + + @Override + public void execute(int n, int[] pmaxf, int[] pmaxp) { + try { + if (fftFactorFunction == null) { + Node bind = Message.createInvoke(1).createNode(); + fftFactorFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, findSymbol(FFT_FACTOR, dlsymNode).asTruffleObject(), "bind", FFT_FACTOR_SIGNATURE); + } + ForeignAccess.sendExecute(factorMessage, fftFactorFunction, n, JavaInterop.asTruffleObject(pmaxf), JavaInterop.asTruffleObject(pmaxp)); + } catch (InteropException t) { + throw RInternalError.shouldNotReachHere(); + } + } + } + + private static class TruffleNFI_WorkNode extends WorkNode { + private static final String FFT_WORK = "fft_work"; + private static final String FFT_WORK_SIGNATURE = "([double], sint32, sint32, sint32, sint32, [double], [sint32]): sint32"; + + @Child DLLRFFI.DLSymNode dlsymNode = RFFIFactory.getRFFI().getDLLRFFI().createDLSymNode(); + @Child Node workMessage = Message.createExecute(7).createNode(); + @CompilationFinal private TruffleObject fftWorkFunction; + + @Override + public int execute(double[] a, int nseg, int n, int nspn, int isn, double[] work, int[] iwork) { + try { + if (fftWorkFunction == null) { + Node bind = Message.createInvoke(1).createNode(); + fftWorkFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, findSymbol(FFT_WORK, dlsymNode).asTruffleObject(), "bind", FFT_WORK_SIGNATURE); + } + return (int) ForeignAccess.sendExecute(workMessage, fftWorkFunction, JavaInterop.asTruffleObject(a), nseg, n, nspn, isn, + JavaInterop.asTruffleObject(work), JavaInterop.asTruffleObject(iwork)); + } catch (InteropException t) { + throw RInternalError.shouldNotReachHere(); + } + } + + } + + private static SymbolHandle findSymbol(String symbol, DLLRFFI.DLSymNode dlsymNode) { + SymbolHandle fftAddress; + DLLInfo dllInfo = DLL.findLibrary("stats"); + assert dllInfo != null; + fftAddress = dlsymNode.execute(dllInfo.handle, symbol); + assert fftAddress != DLL.SYMBOL_NOT_FOUND; + return fftAddress; + } + + @Override + public FactorNode createFactorNode() { + return new TruffleNFI_FactorNode(); + } + + @Override + public WorkNode createWorkNode() { + return new TruffleNFI_WorkNode(); + } + +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java new file mode 100644 index 0000000000000000000000000000000000000000..dd72b7e5e0c62a09f94850a41a4c0dcb20711f06 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java @@ -0,0 +1,104 @@ +/* + * 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 + * 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.ffi.nfi; + +import java.io.IOException; + +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.InteropException; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.java.JavaInterop; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.nodes.ffi.RFFIUtils; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.conn.RConnection; +import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.RTruffleObject; +import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.ffi.DLL; +import com.oracle.truffle.r.runtime.ffi.ToolsRFFI; +import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; +import com.oracle.truffle.r.runtime.ffi.DLLRFFI; +import com.oracle.truffle.r.runtime.ffi.generic.Generic_Tools; + +public class TruffleNFI_Tools implements ToolsRFFI { + + private static class TruffleNFI_ToolsRFFINode extends Generic_Tools.Generic_ToolsRFFINode { + private interface RConnGetC { + int getc(RConnection conn); + } + + private static class RConnGetCImpl implements RConnGetC, RTruffleObject { + @Override + public int getc(RConnection conn) { + RFFIUtils.traceUpCall("getc"); + try { + int r = conn.getc(); + RFFIUtils.traceUpCallReturn("getc", r); + return r; + } catch (IOException ex) { + return -1; + } + } + } + + private static boolean initialized; + + @Child private DLLRFFI.DLSymNode dysymNode = DLLRFFI.DLSymNode.create(); + + @Override + public synchronized Object execute(RConnection con, REnvironment srcfile, RLogicalVector verbose, RLogicalVector fragment, RStringVector basename, RLogicalVector warningCalls, Object macros, + RLogicalVector warndups) { + if (!initialized) { + initCallback(); + initialized = true; + } + return super.execute(con, srcfile, verbose, fragment, basename, warningCalls, JavaInterop.asTruffleObject(macros), warndups); + } + + private void initCallback() { + DLLInfo toolsDLLInfo = DLL.findLibrary(TOOLS); + assert toolsDLLInfo != null; + SymbolHandle symbolHandle = dysymNode.execute(toolsDLLInfo.handle, "gramRd_nfi_init"); + assert symbolHandle != DLL.SYMBOL_NOT_FOUND; + Node bind = Message.createInvoke(1).createNode(); + Node executeNode = Message.createExecute(1).createNode(); + try { + TruffleObject function = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", "((object): sint32): void"); + ForeignAccess.sendExecute(executeNode, function, new RConnGetCImpl()); + } catch (InteropException t) { + throw RInternalError.shouldNotReachHere(t); + } + + } + } + + @Override + public ParseRdNode createParseRdNode() { + return new TruffleNFI_ToolsRFFINode(); + } + +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UpCallsRFFIImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UpCallsRFFIImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..e302c637ca4d9da0529b84a931890bfa050a152a --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UpCallsRFFIImpl.java @@ -0,0 +1,100 @@ +/* + * 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 + * 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.ffi.nfi; + +import com.oracle.truffle.r.nodes.ffi.JavaUpCallsRFFIImpl; +import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper; +import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; + +public class TruffleNFI_UpCallsRFFIImpl extends JavaUpCallsRFFIImpl { + @Override + public Object Rf_mkCharLenCE(Object bytes, int len, int encoding) { + // "bytes" is actually a TruffleObject denoting a native pointer + // TODO: handle encoding properly + return CharSXPWrapper.create(TruffleNFI_Utils.convertCstring(bytes, len)); + } + + @Override + public Object INTEGER(Object x) { + long arrayAddress = TruffleNFI_NativeArray.findArray(x); + if (arrayAddress == 0) { + Object array = super.INTEGER(x); + arrayAddress = TruffleNFI_NativeArray.recordArray(x, array, SEXPTYPE.INTSXP); + } else { + TruffleNFI_Call.returnArrayExisting(SEXPTYPE.INTSXP, arrayAddress); + } + return x; + } + + @Override + public Object LOGICAL(Object x) { + long arrayAddress = TruffleNFI_NativeArray.findArray(x); + if (arrayAddress == 0) { + Object array = super.LOGICAL(x); + arrayAddress = TruffleNFI_NativeArray.recordArray(x, array, SEXPTYPE.LGLSXP); + } else { + TruffleNFI_Call.returnArrayExisting(SEXPTYPE.LGLSXP, arrayAddress); + } + return x; + + } + + @Override + public Object REAL(Object x) { + long arrayAddress = TruffleNFI_NativeArray.findArray(x); + if (arrayAddress == 0) { + Object array = super.LOGICAL(x); + arrayAddress = TruffleNFI_NativeArray.recordArray(x, array, SEXPTYPE.REALSXP); + } else { + TruffleNFI_Call.returnArrayExisting(SEXPTYPE.REALSXP, arrayAddress); + } + return x; + + } + + @Override + public Object RAW(Object x) { + long arrayAddress = TruffleNFI_NativeArray.findArray(x); + if (arrayAddress == 0) { + Object array = super.LOGICAL(x); + arrayAddress = TruffleNFI_NativeArray.recordArray(x, array, SEXPTYPE.RAWSXP); + } else { + TruffleNFI_Call.returnArrayExisting(SEXPTYPE.RAWSXP, arrayAddress); + } + return x; + } + + @Override + public Object R_CHAR(Object x) { + long arrayAddress = TruffleNFI_NativeArray.findArray(x); + if (arrayAddress == 0) { + CharSXPWrapper charSXP = (CharSXPWrapper) x; + Object array = charSXP.getContents().getBytes(); + arrayAddress = TruffleNFI_NativeArray.recordArray(x, array, SEXPTYPE.CHARSXP); + } else { + TruffleNFI_Call.returnArrayExisting(SEXPTYPE.CHARSXP, arrayAddress); + } + return x; + } + +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UserRng.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UserRng.java new file mode 100644 index 0000000000000000000000000000000000000000..e94994edaf5cceb5843f062d8836a40112c4d8d1 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UserRng.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2017, 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.ffi.nfi; + +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.nodes.Node; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.ffi.UserRngRFFI; +import com.oracle.truffle.r.runtime.rng.user.UserRNG.Function; + +public class TruffleNFI_UserRng implements UserRngRFFI { + + private static class NFIUserRngRFFINode extends UserRngRFFINode { + Node initMessage; + Node randMessage; + Node nSeedMessage; + Node seedsMessage; + Node readPointerNode = Message.createExecute(1).createNode(); + + TruffleObject initFunction; + TruffleObject nSeedFunction; + TruffleObject randFunction; + TruffleObject seedsFunction; + + @Override + public void init(int seed) { + if (initMessage == null) { + initMessage = Message.createExecute(1).createNode(); + } + try { + if (initFunction == null) { + Node bind = Message.createInvoke(1).createNode(); + initFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, Function.Init.getSymbolHandle().asTruffleObject(), "bind", "(sint32): void"); + } + ForeignAccess.sendExecute(initMessage, initFunction, seed); + } catch (Throwable t) { + throw RInternalError.shouldNotReachHere(); + } + } + + @Override + public double rand() { + if (randMessage == null) { + randMessage = Message.createExecute(0).createNode(); + } + try { + if (randFunction == null) { + Node bind = Message.createInvoke(1).createNode(); + randFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, Function.Rand.getSymbolHandle().asTruffleObject(), "bind", "(): pointer"); + } + Object address = ForeignAccess.sendExecute(randMessage, randFunction); + Object value = ForeignAccess.sendExecute(readPointerNode, TruffleNFI_CAccess.Function.READ_POINTER_DOUBLE.getSymbolFunction(), address); + return (double) value; + } catch (Throwable t) { + throw RInternalError.shouldNotReachHere(); + } + } + + @Override + public int nSeed() { + if (nSeedMessage == null) { + nSeedMessage = Message.createExecute(0).createNode(); + } + try { + if (nSeedFunction == null) { + Node bind = Message.createInvoke(1).createNode(); + nSeedFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, Function.NSeed.getSymbolHandle().asTruffleObject(), "bind", "(): pointer"); + } + Object address = ForeignAccess.sendExecute(nSeedMessage, nSeedFunction); + Object n = ForeignAccess.sendExecute(readPointerNode, TruffleNFI_CAccess.Function.READ_POINTER_INT.getSymbolFunction(), address); + return (int) n; + } catch (Throwable t) { + throw RInternalError.shouldNotReachHere(); + } + } + + @Override + public void seeds(int[] n) { + if (seedsMessage == null) { + seedsMessage = Message.createExecute(0).createNode(); + } + try { + if (seedsFunction == null) { + Node bind = Message.createInvoke(1).createNode(); + seedsFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, Function.Seedloc.getSymbolHandle().asTruffleObject(), "bind", "(): pointer"); + } + Object address = ForeignAccess.sendExecute(seedsMessage, seedsFunction); + for (int i = 0; i < n.length; i++) { + Object seed = ForeignAccess.sendExecute(readPointerNode, TruffleNFI_CAccess.Function.READ_ARRAY_INT.getSymbolFunction(), address, i); + n[i] = (int) seed; + } + } catch (Throwable t) { + throw RInternalError.shouldNotReachHere(); + } + } + } + + @Override + public UserRngRFFINode createUserRngRFFINode() { + return new NFIUserRngRFFINode(); + } +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java new file mode 100644 index 0000000000000000000000000000000000000000..55b6efe6d4374eb9d1da7b142ea7ee09bb5d6601 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java @@ -0,0 +1,121 @@ +/* + * 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 + * 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.ffi.nfi; + +import java.nio.charset.StandardCharsets; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.TruffleLanguage.Env; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.InteropException; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.r.engine.interop.UnsafeAdapter; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.ffi.DLL; + +public class TruffleNFI_Utils { + + private static String getString(long address, int len) { + byte[] byteArray = new byte[len]; + for (int i = 0; i < len; i++) { + byteArray[i] = UnsafeAdapter.UNSAFE.getByte(address + i); + } + return new String(byteArray, StandardCharsets.UTF_8); + } + + static String convertCstring(Object cstring, int len) { + try { + long address = (long) ForeignAccess.sendUnbox(Message.UNBOX.createNode(), (TruffleObject) cstring); + return getString(address, len); + } catch (UnsupportedMessageException ex) { + throw RInternalError.shouldNotReachHere(ex); + } + } + + private static TruffleObject defaultLibrary; + + @TruffleBoundary + private static void initDefaultLibrary() { + if (defaultLibrary == null) { + Env env = RContext.getInstance().getEnv(); + defaultLibrary = (TruffleObject) env.parse(Source.newBuilder("default").name("(load default)").mimeType("application/x-native").build()).call(); + } + + } + + /** + * Looks up the symbol {@code name} in either the "default" library (e.g. C library symbols) or + * in one of the libraries loaded through {@link DLL}, and binds the given NFI signature to the + * result, returning the resulting Truffle function object. Failure is fatal. + */ + static TruffleObject lookupAndBind(String name, boolean inDefaultLibrary, String signature) { + initDefaultLibrary(); + try { + TruffleObject symbol; + if (inDefaultLibrary) { + symbol = ((TruffleObject) ForeignAccess.sendRead(Message.READ.createNode(), defaultLibrary, name)); + } else { + symbol = DLL.findSymbol(name, null).asTruffleObject(); + } + return (TruffleObject) ForeignAccess.sendInvoke(Message.createInvoke(1).createNode(), symbol, "bind", signature); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + /** + * Returns the number of arguments in an NFI signature. + */ + static int getArgCount(String signature) { + int argCount = 0; + int nestCount = -1; + boolean type = false; + for (int i = 0; i < signature.length(); i++) { + char ch = signature.charAt(i); + if (ch == '(') { + nestCount++; + } else if (ch == ')') { + if (nestCount > 0) { + nestCount--; + } else { + return type ? argCount + 1 : 0; + } + } else if (ch == ',') { + if (nestCount == 0) { + argCount++; + } + } else { + type = true; + } + } + throw RInternalError.shouldNotReachHere(); + } + + public static void main(String[] args) { + System.out.printf("argCount: %s%n", getArgCount(args[0])); + } +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Zip.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Zip.java new file mode 100644 index 0000000000000000000000000000000000000000..957b88ea243c08d4ee217dcf951bc25882d321ec --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Zip.java @@ -0,0 +1,103 @@ +/* + * 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 + * 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.ffi.nfi; + +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.InteropException; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.java.JavaInterop; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.ffi.ZipRFFI; + +public class TruffleNFI_Zip implements ZipRFFI { + + private enum Function { + compress("([uint8], [uint64], [uint8], uint64): sint32"), + uncompress("([uint8], [uint64], [uint8], uint64): sint32"); + + private final int argCount; + private final String signature; + private Node executeNode; + private TruffleObject function; + + Function(String signature) { + this.argCount = TruffleNFI_Utils.getArgCount(signature); + this.signature = signature; + } + + private void initialize() { + if (executeNode == null) { + executeNode = Message.createExecute(argCount).createNode(); + } + if (function == null) { + function = TruffleNFI_Utils.lookupAndBind(name(), true, signature); + } + } + } + + private static class TruffleNFI_CompressNode extends ZipRFFI.CompressNode { + + @Override + public int execute(byte[] dest, byte[] source) { + Function.compress.initialize(); + long[] destlen = new long[]{dest.length}; + try { + int result = (int) ForeignAccess.sendExecute(Function.compress.executeNode, Function.compress.function, + JavaInterop.asTruffleObject(dest), JavaInterop.asTruffleObject(destlen), + JavaInterop.asTruffleObject(source), JavaInterop.asTruffleObject(source.length)); + return result; + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + private static class TruffleNFI_UncompressNode extends ZipRFFI.UncompressNode { + @Override + public int execute(byte[] dest, byte[] source) { + Function.uncompress.initialize(); + long[] destlen = new long[]{dest.length}; + try { + int result = (int) ForeignAccess.sendExecute(Function.uncompress.executeNode, Function.uncompress.function, + JavaInterop.asTruffleObject(dest), JavaInterop.asTruffleObject(destlen), + JavaInterop.asTruffleObject(source), JavaInterop.asTruffleObject(source.length)); + return result; + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + @Override + public CompressNode createCompressNode() { + return new TruffleNFI_CompressNode(); + } + + @Override + public UncompressNode createUncompressNode() { + return new TruffleNFI_UncompressNode(); + } + +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..2c18397bf7f432a3a4d80572fef3d634c022cdb6 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java @@ -0,0 +1,151 @@ +/* + * 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.engine.shell; + +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.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 { + private final ConsoleHandler console; + + private static boolean isTesting = false; + + public static void testingMode() { + isTesting = true; + } + + public JLineConsoleCompleter(ConsoleHandler console) { + this.console = console; + } + + @Override + public int complete(String buffer, int cursor, List<CharSequence> candidates) { + try { + return completeImpl(buffer, cursor, candidates); + } catch (Throwable e) { + if (isTesting) { + throw e; + } + RInternalError.reportErrorAndConsoleLog(e, console, 0); + } + return cursor; + } + + private static 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; + } + + 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)); + } + Collections.sort(ret, String.CASE_INSENSITIVE_ORDER); + candidates.addAll(ret); + return start; + } + + private static int getStart(String buffer, REnvironment env, int cursor) { + int start = 0; + Object o = env.get("options"); + if (o instanceof RList) { + RList opt = (RList) o; + start = lastIdxOf(buffer, opt, "funarg.suffix", start, cursor); + start = lastIdxOf(buffer, opt, "function.suffix", start, cursor); + } + start = lastIdxOf(buffer, "\"", start, cursor); + start = lastIdxOf(buffer, "'", start, cursor); + return start; + } + + private static int lastIdxOf(String buffer, RList opt, String key, int start, int cursor) { + int optIdx = opt.getElementIndexByName(key); + if (optIdx > -1) { + Object o = opt.getDataAt(optIdx); + if (o instanceof RAbstractStringVector) { + RAbstractStringVector v = (RAbstractStringVector) o; + return lastIdxOf(buffer, v.getLength() > 0 ? v.getDataAt(0) : null, start, cursor); + } + } + return start; + } + + private static int lastIdxOf(String buffer, String subs, int start, int cursor) { + if (null != subs && !subs.isEmpty()) { + int idx = buffer.lastIndexOf(subs, cursor); + if (idx == cursor) { + idx = buffer.lastIndexOf(subs, cursor - 1); + } + if (idx > -1) { + idx += subs.length(); + return idx > start ? idx : start; + } + } + return start; + } +} 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 2c6f86297d727f7862e273cf4c5faa1bdeb9ef88..18ced0d667c767e10df4217d3bdd630da2cbb77e 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 @@ -47,6 +47,7 @@ class JLineConsoleHandler implements ConsoleHandler { JLineConsoleHandler(RStartParams startParams, InputStream inStream, OutputStream outStream) { try { console = new ConsoleReader(inStream, outStream); + console.addCompleter(new JLineConsoleCompleter(this)); console.setHandleUserInterrupt(true); console.setExpandEvents(false); } catch (IOException ex) { @@ -76,11 +77,7 @@ class JLineConsoleHandler implements ConsoleHandler { public String readLine() { try { console.getTerminal().init(); - String line = console.readLine(); - if (line != null) { - line += "\n"; - } - return line; + return console.readLine(); } catch (UserInterruptException e) { throw e; } catch (Exception ex) { 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 c5dd80595da815447022752ad11e57cd6fed3b00..9f159f813512fb6ae93d57a02795069172011266 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 @@ -38,6 +38,7 @@ import java.util.List; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.vm.PolyglotEngine; +import com.oracle.truffle.api.vm.PolyglotEngine.Value; import com.oracle.truffle.r.nodes.builtin.base.Quit; import com.oracle.truffle.r.runtime.ExitException; import com.oracle.truffle.r.runtime.JumpToTopLevelException; @@ -77,8 +78,8 @@ public class RCommand { public static int doMain(String[] args, String[] env, boolean initial, InputStream inStream, OutputStream outStream) { RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.R, args, false); options.printHelpAndVersion(); - PolyglotEngine vm = createPolyglotEngineFromCommandLine(options, false, initial, inStream, outStream, env); - return readEvalPrint(vm); + ContextInfo info = createContextInfoFromCommandLine(options, false, initial, inStream, outStream, env); + return readEvalPrint(info.createVM(), info); } /** @@ -88,7 +89,7 @@ public class RCommand { return input.replace("~+~", " "); } - static PolyglotEngine createPolyglotEngineFromCommandLine(RCmdOptions options, boolean embedded, boolean initial, InputStream inStream, OutputStream outStream, String[] env) { + static ContextInfo createContextInfoFromCommandLine(RCmdOptions options, boolean embedded, boolean initial, InputStream inStream, OutputStream outStream, String[] env) { RStartParams rsp = new RStartParams(options, embedded); String fileArg = options.getString(FILE); @@ -184,7 +185,7 @@ public class RCommand { } } } - return ContextInfo.create(rsp, env, ContextKind.SHARE_NOTHING, initial ? null : RContext.getInstance(), consoleHandler).createVM(); + return ContextInfo.create(rsp, env, ContextKind.SHARE_NOTHING, initial ? null : RContext.getInstance(), consoleHandler); } private static final Source GET_ECHO = RSource.fromTextInternal("invisible(getOption('echo'))", RSource.Internal.GET_ECHO); @@ -201,10 +202,9 @@ public class RCommand { * In case 2, we must implicitly execute a {@code quit("default, 0L, TRUE} command before * exiting. So,in either case, we never return. */ - static int readEvalPrint(PolyglotEngine vm) { + static int readEvalPrint(PolyglotEngine vm, ContextInfo info) { int lastStatus = 0; - ContextInfo contextInfo = ContextInfo.getContextInfo(vm); - ConsoleHandler consoleHandler = contextInfo.getConsoleHandler(); + ConsoleHandler consoleHandler = info.getConsoleHandler(); try { // console.println("initialize time: " + (System.currentTimeMillis() - start)); REPL: for (;;) { @@ -224,11 +224,15 @@ public class RCommand { String continuePrompt = getContinuePrompt(); StringBuffer sb = new StringBuffer(input); Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.SHELL_INPUT); + boolean hasExecutor = RContext.getInstance().hasExecutor(); while (true) { lastStatus = 0; try { try { - vm.eval(source); + Value val = vm.eval(source); + if (hasExecutor) { + val.get(); + } // checked exceptions are wrapped in RuntimeExceptions } catch (RuntimeException e) { if (e.getCause() instanceof com.oracle.truffle.api.vm.IncompleteSourceException) { @@ -243,6 +247,7 @@ public class RCommand { if (additionalInput == null) { throw new EOFException(); } + sb.append('\n'); sb.append(additionalInput); source = RSource.fromTextInternal(sb.toString(), RSource.Internal.SHELL_INPUT); // The only continuation in the while loop @@ -260,7 +265,7 @@ public class RCommand { } catch (ExitException e) { // usually from quit int status = e.getStatus(); - if (contextInfo.getParent() == null) { + if (info.getParent() == null) { vm.dispose(); Utils.systemExit(status); } else { @@ -281,12 +286,12 @@ public class RCommand { // JumpToTopLevelException can happen if user profile invokes browser (unlikely but // possible) try { - vm.eval(QUIT_EOF); + vm.eval(QUIT_EOF).get(); } catch (JumpToTopLevelException e) { Utils.systemExit(0); } catch (ExitException e) { // normal quit, but with exit code based on lastStatus - if (contextInfo.getParent() == null) { + if (info.getParent() == null) { Utils.systemExit(lastStatus); } else { return lastStatus; diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java index d0031dd9f6d0c394ef56f41ec992a90c4ae36d50..d396a37419bbc799889fdca017ec5db3f5e8af88 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java @@ -54,24 +54,28 @@ import com.oracle.truffle.r.runtime.context.RContext; * object which is itself stored as a global symbol in the associated {@link PolyglotEngine} * instance. The FastR {@link PolyglotEngine} is then partially initialized. The call to * {@code R_SetParams} will adjust the values stored in the {@link RStartParams} object and then - * {@code Rf_mainloop}, which calls {@link #setupRmainloop(PolyglotEngine)} and then - * {@link #runRmainloop(PolyglotEngine)}, which will complete the FastR initialization and enter the - * read-eval-print loop. + * {@code Rf_mainloop}, which calls {@link #setupRmainloop()} and then {@link #runRmainloop()}, + * which will complete the FastR initialization and enter the read-eval-print loop. */ public class REmbedded { + private static ContextInfo info; + private static PolyglotEngine vm; + /** * Creates the {@link PolyglotEngine} and initializes it. Called from native code when FastR is * embedded. Corresponds to FFI method {@code Rf_initialize_R}. N.B. This does not completely * initialize FastR as we cannot do that until the embedding system has had a chance to adjust * the {@link RStartParams}, which happens after this call returns. */ - private static PolyglotEngine initializeR(String[] args) { + private static void initializeR(String[] args) { + assert vm == null; + assert info == null; RContext.setEmbedded(); RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.R, args, true); - PolyglotEngine vm = RCommand.createPolyglotEngineFromCommandLine(options, true, true, System.in, System.out, null); + info = RCommand.createContextInfoFromCommandLine(options, true, true, System.in, System.out, null); + vm = info.createVM(); vm.eval(INIT); - return vm; } /** @@ -85,32 +89,33 @@ public class REmbedded { * GnuR distinguishes {@code setup_Rmainloop} and {@code run_Rmainloop}. Currently we don't have * the equivalent separation in FastR. */ - private static void setupRmainloop(@SuppressWarnings("unused") PolyglotEngine vm) { + private static void setupRmainloop() { + // nothing to do } /** * This is where we can complete the initialization based on what modifications were made by the * native code after {@link #initializeR} returned. */ - private static void runRmainloop(PolyglotEngine vm) { + private static void runRmainloop() { RContext.getInstance().completeEmbeddedInitialization(); if (!RContext.getInstance().getStartParams().getQuiet()) { RContext.getInstance().getConsoleHandler().println(RRuntime.WELCOME_MESSAGE); } - RCommand.readEvalPrint(vm); + RCommand.readEvalPrint(vm, info); } /** * Testing vehicle, emulates a native upcall. */ public static void main(String[] args) { - PolyglotEngine vm = initializeR(args); - RStartParams startParams = ContextInfo.getContextInfo(vm).getStartParams(); + initializeR(args); + RStartParams startParams = info.getStartParams(); startParams.setEmbedded(); startParams.setLoadInitFile(false); startParams.setNoRenviron(true); - setupRmainloop(vm); - runRmainloop(vm); + setupRmainloop(); + runRmainloop(); } // Checkstyle: stop method name check diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RMain.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RMain.java new file mode 100644 index 0000000000000000000000000000000000000000..4a65dc84dbbce67cdc35a1cfb883e4dcd9a32547 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RMain.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, 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.shell; + +/** + * Convenience class that allows the R/Rscript entry to be chosen by an initial argument. + */ +public class RMain { + + public static void main(String[] args) { + boolean rscript = false; + if (args.length > 0) { + String arg = args[0]; + switch (arg) { + case "R": + case "r": + break; + + case "Rscript": + case "rscript": + rscript = true; + break; + + default: + System.out.println(arg); + usage(); + } + String[] xargs = shiftArgs(args); + if (rscript) { + RscriptCommand.main(xargs); + } else { + RCommand.main(xargs); + } + } else { + usage(); + } + } + + private static void usage() { + System.out.println("usage: [R|Rscript] ..."); + System.exit(1); + } + + private static String[] shiftArgs(String[] args) { + String[] nargs = new String[args.length - 1]; + System.arraycopy(args, 1, nargs, 0, nargs.length); + return nargs; + } + +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java index 1af3eff3eb6a6efbacccde9875bac1e9b928a5de..8e2be1e76aed3fc5cbcf73cf771740305479cf3e 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.engine.shell; +import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.DEFAULT_PACKAGES; import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.EXPR; import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.FILE; import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.HELP; @@ -33,17 +34,16 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; -import com.oracle.truffle.api.vm.PolyglotEngine; import com.oracle.truffle.r.runtime.RCmdOptions; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RVersionNumber; +import com.oracle.truffle.r.runtime.context.ContextInfo; /** * Emulates the (Gnu)Rscript command as precisely as possible. in GnuR, Rscript is a genuine wrapper * to R, as evidenced by the script {@code print(commandArgs())}. We don't implement it quite that * way but the effect is similar. * - * TODO support {@code --default-packages} option. */ public class RscriptCommand { // CheckStyle: stop system..print check @@ -77,6 +77,14 @@ public class RscriptCommand { options.setValue(FILE, arguments[firstNonOptionArgIndex]); } } + String defaultPackagesArg = options.getString(DEFAULT_PACKAGES); + String defaultPackagesEnv = System.getenv("R_DEFAULT_PACKAGES"); + if (defaultPackagesArg == null && defaultPackagesEnv == null) { + defaultPackagesArg = "datasets,utils,grDevices,graphics,stats"; + } + if (defaultPackagesEnv == null) { + options.setValue(DEFAULT_PACKAGES, defaultPackagesArg); + } // copy up to non-option args int rx = 1; while (rx < firstNonOptionArgIndex) { @@ -109,8 +117,8 @@ public class RscriptCommand { // Handle --help and --version specially, as they exit. RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.RSCRIPT, args, false); preprocessRScriptOptions(options); - PolyglotEngine vm = RCommand.createPolyglotEngineFromCommandLine(options, false, initial, inStream, outStream, env); - return RCommand.readEvalPrint(vm); + ContextInfo info = RCommand.createContextInfoFromCommandLine(options, false, initial, inStream, outStream, env); + return RCommand.readEvalPrint(info.createVM(), info); } 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 60af1f537c607a7152802ea422b86f8dd4459c78..51af0bead26b43b0fa393bd666900a01a7a1fcc2 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 @@ -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 @@ -64,7 +64,7 @@ class StringConsoleHandler implements ConsoleHandler { output.print(prompt); output.println(lines.get(currentLine)); } - return lines.get(currentLine++) + "\n"; + return lines.get(currentLine++); } else { return null; } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Arrows.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Arrows.java new file mode 100644 index 0000000000000000000000000000000000000000..c2cd454c0010b03af51eaba66b890515234f70b1 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Arrows.java @@ -0,0 +1,95 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContainer; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asInt; + +import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext; +import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; + +final class Arrows { + // Structure of an arrow description + private static final int ARROWANGLE = 0; + private static final int ARROWLENGTH = 1; + private static final int ARROWENDS = 2; + private static final int ARROWTYPE = 3; + // known values of ARROWTYPE + private static final int ARROWTYPE_LINES = 1; + private static final int ARROWTYPE_POLYGON = 2; + + /** + * Draws arrows at the start and end of given lines. + * + * @param x x-positions of the line(s) + * @param y y-positions of the line(s) + * @param startIndex consider arrays x,y to start from this index + * @param length consider arrays x,y to have this length + * @param parentIndex the index of the line we are drawing, this is used for choosing the right + * index into vectors extracted from arrow + * @param arrow list with various attributes of the arrow + * @param start should we draw start arrow if the arrow list says so. Otherwise never draw it. + * @param end should we draw end arrow if the arrow list says so. Otherwise never draw it. + * @param conversionCtx needed for unit conversions. + */ + public static void drawArrows(double[] x, double[] y, int startIndex, int length, int parentIndex, RList arrow, boolean start, boolean end, UnitConversionContext conversionCtx) { + assert x.length == y.length; + int endsVal = asInt(arrow.getDataAt(ARROWENDS), parentIndex); + boolean first = endsVal != 2; + boolean last = endsVal != 1; + if ((!first || !start) && (!last || !end)) { + // if we are not going to draw any arrow anyway, just finish + return; + } + // extract angle, length in inches and arrow type from 'arrow' + double angle = asDouble(arrow.getDataAt(ARROWANGLE), parentIndex); + int arrowType = asInt(arrow.getDataAt(ARROWTYPE), parentIndex); + RAbstractContainer lengthVec = asAbstractContainer(arrow.getDataAt(ARROWLENGTH)); + double arrowLength = Unit.convertHeight(lengthVec, parentIndex, conversionCtx); + arrowLength = Math.max(arrowLength, Unit.convertWidth(lengthVec, parentIndex, conversionCtx)); + // draw the arrows + GridDevice device = conversionCtx.device; + DrawingContext drawingCtx = conversionCtx.gpar.getDrawingContext(parentIndex); + if (first && start) { + drawArrow(drawingCtx, device, arrowType, x[startIndex], y[startIndex], x[startIndex + 1], y[startIndex + 1], angle, arrowLength); + } + if (last && end) { + int n = startIndex + length; + drawArrow(drawingCtx, device, arrowType, x[n - 1], y[n - 1], x[n - 2], y[n - 2], angle, arrowLength); + } + } + + private static void drawArrow(DrawingContext drawingCtx, GridDevice device, int arrowType, double x0, double y0, double x1, double y1, double angle, double length) { + double a = Math.toRadians(angle); + double xc = x1 - x0; + double yc = y1 - y0; + double rot = Math.atan2(yc, xc); + double[] vertx = new double[3]; + double[] verty = new double[3]; + vertx[0] = x0 + length * Math.cos(rot + a); + verty[0] = y0 + length * Math.sin(rot + a); + vertx[1] = x0; + verty[1] = y0; + vertx[2] = x0 + length * Math.cos(rot - a); + verty[2] = y0 + length * Math.sin(rot - a); + if (arrowType == ARROWTYPE_LINES) { + device.drawPolyLines(drawingCtx, vertx, verty, 0, 3); + } else if (arrowType == ARROWTYPE_POLYGON) { + device.drawPolyLines(drawingCtx, vertx, verty, 0, 3); + // TODO: real polygon + } + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DisplayList.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DisplayList.java new file mode 100644 index 0000000000000000000000000000000000000000..06f33e2aa39c73c53d369278b7485a04ef376a1d --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DisplayList.java @@ -0,0 +1,108 @@ +/* + * 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.toBoolean; + +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.DisplayListFactory.LGetDisplayListElementNodeGen; +import com.oracle.truffle.r.library.fastrGrid.DisplayListFactory.LSetDisplayListOnNodeGen; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; + +public class DisplayList { + private static final int INITIAL_DL_SIZE = 100; + + static RList createInitialDisplayList() { + Object[] data = new Object[INITIAL_DL_SIZE]; + Arrays.fill(data, 0, data.length, RNull.instance); + RList list = RDataFactory.createList(data); + list.makeSharedPermanent(); + return list; + } + + static void initDisplayList(GridState gridState) { + RList list = createInitialDisplayList(); + list.setDataAt(list.getInternalStore(), 0, gridState.getViewPort()); + gridState.setDisplayList(list); + gridState.setDisplayListIndex(1); + } + + public abstract static class LGetDisplayListElement extends RExternalBuiltinNode.Arg1 { + static { + Casts casts = new Casts(LGetDisplayListElement.class); + casts.arg(0).asIntegerVector().findFirst(); + } + + public static LGetDisplayListElement create() { + return LGetDisplayListElementNodeGen.create(); + } + + @Specialization + @TruffleBoundary + Object getDLElement(int index) { + return GridContext.getContext().getGridState().getDisplayList().getDataAt(index); + } + } + + public abstract static class LSetDisplayListOn extends RExternalBuiltinNode.Arg1 { + static { + Casts casts = new Casts(LSetDisplayListOn.class); + casts.arg(0).asLogicalVector().findFirst().map(toBoolean()); + } + + public static LSetDisplayListOn create() { + return LSetDisplayListOnNodeGen.create(); + } + + @Specialization + @TruffleBoundary + byte setDLOn(boolean value) { + GridState gridState = GridContext.getContext().getGridState(); + boolean result = gridState.isDisplayListOn(); + gridState.setIsDisplayListOn(value); + return RRuntime.asLogical(result); + } + } + + public static final class LInitDisplayList extends RExternalBuiltinNode.Arg0 { + static { + Casts.noCasts(LInitDisplayList.class); + } + + @Override + @TruffleBoundary + public Object execute() { + GridState gridState = GridContext.getContext().getGridState(); + initDisplayList(gridState); + return RNull.instance; + } + + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java new file mode 100644 index 0000000000000000000000000000000000000000..f2d1290c6e10fd3c4f50de1f5d7aa8f74d3e51c4 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java @@ -0,0 +1,393 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContainer; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asList; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asListOrNull; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.sum; +import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.flatten; +import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.fromFlat; +import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.multiply; +import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.rotation; +import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.translation; +import static com.oracle.truffle.r.library.fastrGrid.Unit.newUnit; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext; +import com.oracle.truffle.r.library.fastrGrid.ViewPort.LayoutPos; +import com.oracle.truffle.r.library.fastrGrid.ViewPort.LayoutSize; +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.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.env.REnvironment; + +final class DoSetViewPort { + + private DoSetViewPort() { + // only static members + } + + /** + * Prepares the given view-port to be set as the current view-port, calculates necessary + * information for the new current view-port. + * + * @see #calcViewportTransform(RList, Object, boolean, GridDevice, GPar) + */ + @TruffleBoundary + public static RList doSetViewPort(RList pushedViewPort, boolean hasParent, boolean pushing) { + GridState gridState = GridContext.getContext().getGridState(); + Object[] pushedVPData = pushedViewPort.getDataWithoutCopying(); + if (hasParent && pushing) { + RList parent = gridState.getViewPort(); + pushedVPData[ViewPort.PVP_PARENT] = parent; + REnvironment children = GridUtils.asEnvironment(parent.getDataAt(ViewPort.PVP_CHILDREN)); + children.safePut(RRuntime.asString(pushedVPData[ViewPort.VP_NAME]), pushedViewPort); + } + + GridDevice currentDevice = GridContext.getContext().getCurrentDevice(); + GPar gpar = GridState.getInitialGPar(currentDevice); + + RList parent = asListOrNull(pushedViewPort.getDataAt(ViewPort.PVP_PARENT)); + boolean doNotRecalculateParent = hasParent && !ViewPort.updateDeviceSizeInVP(parent, currentDevice); + calcViewportTransform(pushedViewPort, parent, doNotRecalculateParent, currentDevice, gpar); + + // TODO: clipping + pushedVPData[ViewPort.PVP_CLIPRECT] = RDataFactory.createDoubleVector(new double[]{0, 0, 0, 0}, RDataFactory.COMPLETE_VECTOR); + pushedVPData[ViewPort.PVP_DEVWIDTHCM] = scalar(Unit.inchesToCm(currentDevice.getWidth())); + pushedVPData[ViewPort.PVP_DEVHEIGHTCM] = scalar(Unit.inchesToCm(currentDevice.getHeight())); + + assert pushedViewPort.verify(); + return pushedViewPort; + } + + /** + * Calculates and sets the view-port width and height in inches, and transformation matrix and + * rotation angle. + * + * @param viewPort The view-port to be updated. + * @param parent The parent of the view-port, null if the view-port is top level. + * @param incremental If {@code true} it is assumed that we can just take the transformation + * matrix and other values from the parent without re-calculating them recursively. + * @param device This method needs the device in order to convert units + * @param deviceTopLevelGpar This method needs to know the device default drawing context in + * order to convert units for the top level view port + */ + @TruffleBoundary + public static void calcViewportTransform(RList viewPort, Object parent, boolean incremental, GridDevice device, GPar deviceTopLevelGpar) { + double[][] parentTransform; + ViewPortContext parentContext; + ViewPortLocation vpl; + Size parentSize; + GPar drawingContext; + double parentAngle; + if (parent == null || parent == RNull.instance) { + parentTransform = TransformMatrix.identity(); + parentContext = ViewPortContext.createDefault(); + parentSize = new Size(device.getWidth(), device.getHeight()); + vpl = ViewPortLocation.fromViewPort(viewPort); + drawingContext = deviceTopLevelGpar; + parentAngle = 0; + } else { + assert parent instanceof RList : "inconsistent data: parent of a viewport must be a list"; + RList parentVPList = (RList) parent; + Object[] parentData = parentVPList.getDataWithoutCopying(); + if (!incremental) { + calcViewportTransform(parentVPList, parentData[ViewPort.PVP_PARENT], false, device, deviceTopLevelGpar); + } + parentSize = new Size(Unit.cmToInches(GridUtils.asDouble(parentData[ViewPort.PVP_WIDTHCM])), Unit.cmToInches(GridUtils.asDouble(parentData[ViewPort.PVP_HEIGHTCM]))); + parentTransform = fromFlat(GridUtils.asDoubleVector(parentData[ViewPort.PVP_TRANS]).materialize().getDataWithoutCopying()); + parentContext = ViewPortContext.fromViewPort(parentVPList); + parentAngle = asDouble(parentData[ViewPort.PVP_ROTATION]); + + drawingContext = GPar.create(asList(viewPort.getDataAt(ViewPort.PVP_PARENTGPAR))); + boolean noLayout = (isNull(viewPort.getDataAt(ViewPort.VP_VALIDLPOSROW)) && isNull(viewPort.getDataAt(ViewPort.VP_VALIDLPOSCOL))) || isNull(parentData[ViewPort.VP_LAYOUT]); + if (noLayout) { + vpl = ViewPortLocation.fromViewPort(viewPort); + } else { + vpl = calcViewportLocationFromLayout(getLayoutPos(viewPort, parentVPList), parentVPList, parentSize); + } + } + + UnitConversionContext conversionCtx = new UnitConversionContext(parentSize, parentContext, device, drawingContext); + double xInches = Unit.convertX(vpl.x, 0, conversionCtx); + double yInches = Unit.convertY(vpl.y, 0, conversionCtx); + double width = Unit.convertWidth(vpl.width, 0, conversionCtx); + double height = Unit.convertHeight(vpl.height, 0, conversionCtx); + + if (!Double.isFinite(xInches) || !Double.isFinite(yInches) || !Double.isFinite(width) || !Double.isFinite(height)) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "non-finite location and/or size for viewport"); + } + + double xadj = GridUtils.justification(width, vpl.hjust); + double yadj = GridUtils.justification(height, vpl.vjust); + + // Produce transform for this viewport + double[][] thisLocation = translation(xInches, yInches); + double[][] thisJustification = translation(xadj, yadj); + // Position relative to origin of rotation THEN rotate. + double viewPortAngle = asDouble(viewPort.getDataAt(ViewPort.VP_ANGLE)); + double[][] thisRotation = rotation(viewPortAngle); + double[][] tempTransform = multiply(thisJustification, thisRotation); + // Translate to bottom-left corner. + double[][] thisTransform = multiply(tempTransform, thisLocation); + // Combine with parent's transform + double[][] transform = multiply(thisTransform, parentTransform); + + // Sum up the rotation angles + double rotationAngle = parentAngle + viewPortAngle; + + // Finally, allocate the rows and columns for this viewport's layout if it has one + if (!isNull(viewPort.getDataAt(ViewPort.VP_LAYOUT))) { + ViewPortContext vpCtx = ViewPortContext.fromViewPort(viewPort); + calcViewPortLayout(viewPort, new Size(width, height), vpCtx, device, GPar.create(asList(viewPort.getDataAt(ViewPort.PVP_GPAR)))); + } + + Object[] viewPortData = viewPort.getDataWithoutCopying(); + viewPortData[ViewPort.PVP_WIDTHCM] = scalar(Unit.inchesToCm(width)); + viewPortData[ViewPort.PVP_HEIGHTCM] = scalar(Unit.inchesToCm(height)); + viewPortData[ViewPort.PVP_ROTATION] = scalar(rotationAngle); + viewPortData[ViewPort.PVP_TRANS] = RDataFactory.createDoubleVector(flatten(transform), RDataFactory.COMPLETE_VECTOR, new int[]{3, 3}); + } + + private static void calcViewPortLayout(RList viewPort, Size size, ViewPortContext parentVPCtx, GridDevice device, GPar gpar) { + LayoutSize layoutSize = LayoutSize.fromViewPort(viewPort); + double[] npcWidths = new double[layoutSize.ncol]; + double[] npcHeights = new double[layoutSize.nrow]; + boolean[] relativeWidths = new boolean[layoutSize.ncol]; + boolean[] relativeHeights = new boolean[layoutSize.nrow]; + UnitConversionContext conversionCtx = new UnitConversionContext(size, parentVPCtx, device, gpar); + + // For both dimensions we find out which units are other than "null" for those we can + // immediately calculate the physical size in npcWidth/npcHeights. The reducedWidth/Height + // gives us how much of width/height is left after we take up the space by physical units + Object[] layoutData = asList(viewPort.getDataAt(ViewPort.VP_LAYOUT)).getDataWithoutCopying(); + RAbstractContainer layoutWidths = asAbstractContainer(layoutData[ViewPort.LAYOUT_WIDTHS]); + assert Unit.getLength(layoutWidths) == layoutSize.ncol : "inconsistent layout size with layout widths"; + double reducedWidth = getReducedDimension(layoutWidths, npcWidths, relativeWidths, size.getWidth(), conversionCtx, true); + + RAbstractContainer layoutHeights = asAbstractContainer(layoutData[ViewPort.LAYOUT_HEIGHTS]); + assert Unit.getLength(layoutHeights) == layoutSize.nrow : "inconsistent layout size with layout height"; + double reducedHeight = getReducedDimension(layoutHeights, npcHeights, relativeHeights, size.getHeight(), conversionCtx, false); + + // npcHeight (and npcWidth) has some 'holes' in them, at indexes with + // relativeHeights[index]==true, we will calculate the values for them now. + // Firstly allocate the respected widths/heights and calculate how much space remains + RList layoutAsList = asList(viewPort.getDataAt(ViewPort.VP_LAYOUT)); + int respect = RRuntime.asInteger(layoutAsList.getDataAt(ViewPort.LAYOUT_VRESPECT)); + int[] layoutRespectMat = ((RAbstractIntVector) layoutAsList.getDataAt(ViewPort.LAYOUT_MRESPECT)).materialize().getDataWithoutCopying(); + if ((reducedHeight > 0 || reducedWidth > 0) && respect > 0) { + double sumRelWidth = sumRelativeDimension(layoutWidths, relativeWidths, parentVPCtx, device, gpar, true); + double sumRelHeight = sumRelativeDimension(layoutHeights, relativeHeights, parentVPCtx, device, gpar, false); + double tempWidth = reducedWidth; + double tempHeight = reducedHeight; + double denom; + double mult; + // Determine whether aspect ratio of available space is bigger or smaller than + // aspect ratio of layout + if (tempHeight * sumRelWidth > sumRelHeight * tempWidth) { + denom = sumRelWidth; + mult = tempWidth; + } else { + denom = sumRelHeight; + mult = tempHeight; + } + for (int i = 0; i < layoutSize.ncol; i++) { + if (relativeWidths[i] && colRespected(respect, i, layoutRespectMat, layoutSize)) { + /* + * Special case of respect, but sumHeight = 0. Action is to allocate widths as + * if unrespected. Ok to test == 0 because will only be 0 if all relative + * heights are actually exactly 0. + */ + if (sumRelHeight == 0) { + denom = sumRelWidth; + mult = tempWidth; + } + // Build a unit SEXP with a single value and no data + npcWidths[i] = Unit.pureNullUnitValue(layoutWidths, i) / denom * mult; + reducedWidth -= npcWidths[i]; + } + } + for (int i = 0; i < layoutSize.nrow; i++) { + if (relativeHeights[i] && rowRespected(respect, i, layoutRespectMat, layoutSize)) { + if (sumRelWidth == 0) { + denom = sumRelHeight; + mult = tempHeight; + } + npcHeights[i] = Unit.pureNullUnitValue(layoutHeights, i) / denom * mult; + reducedHeight -= npcHeights[i]; + } + } + } else if (respect > 0) { + for (int i = 0; i < layoutSize.ncol; i++) { + if (relativeWidths[i] && colRespected(respect, i, layoutRespectMat, layoutSize)) { + npcWidths[i] = 0; + } + } + for (int i = 0; i < layoutSize.nrow; i++) { + if (relativeHeights[i] && rowRespected(respect, i, layoutRespectMat, layoutSize)) { + npcHeights[i] = 0; + } + } + } + + // Secondly, allocate remaining relative widths and heights in the remaining space + allocateRelativeDim(layoutSize, layoutWidths, npcWidths, relativeWidths, reducedWidth, respect, layoutRespectMat, device, gpar, parentVPCtx, true); + allocateRelativeDim(layoutSize, layoutHeights, npcHeights, relativeHeights, reducedHeight, respect, layoutRespectMat, device, gpar, parentVPCtx, false); + + // Create the result + Object[] vpData = viewPort.getDataWithoutCopying(); + vpData[ViewPort.PVP_WIDTHS] = RDataFactory.createDoubleVector(npcWidths, RDataFactory.COMPLETE_VECTOR); + vpData[ViewPort.PVP_HEIGHTS] = RDataFactory.createDoubleVector(npcHeights, RDataFactory.COMPLETE_VECTOR); + } + + private static void allocateRelativeDim(LayoutSize layoutSize, RAbstractContainer layoutItems, double[] npcItems, boolean[] relativeItems, double reducedDim, int respect, int[] layoutRespectMat, + GridDevice device, GPar gpar, ViewPortContext parentVPCtx, boolean isWidth) { + assert relativeItems.length == npcItems.length; + UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, gpar, 1, 0); + double totalUnrespectedSize = 0; + if (reducedDim > 0) { + for (int i = 0; i < relativeItems.length; i++) { + if (relativeItems[i] && !rowColRespected(respect, i, layoutRespectMat, layoutSize, isWidth)) { + totalUnrespectedSize += Unit.convertDimension(layoutItems, i, layoutModeCtx, isWidth); + } + } + } + // set the remaining width/height to zero or to proportion of totalUnrespectedSize + for (int i = 0; i < relativeItems.length; i++) { + if (relativeItems[i] && !rowColRespected(respect, i, layoutRespectMat, layoutSize, isWidth)) { + npcItems[i] = 0; + if (totalUnrespectedSize > 0) { + // if there was some with left, then totalUnrespectedSize contains sum of it + npcItems[i] = reducedDim * Unit.convertDimension(layoutItems, i, layoutModeCtx, isWidth) / totalUnrespectedSize; + } + } + } + } + + private static boolean rowColRespected(int respected, int rowOrCol, int[] layoutRespectMat, LayoutSize layoutSize, boolean isColumn) { + return isColumn ? colRespected(respected, rowOrCol, layoutRespectMat, layoutSize) : rowRespected(respected, rowOrCol, layoutRespectMat, layoutSize); + } + + private static boolean rowRespected(int respected, int row, int[] layoutRespectMat, LayoutSize layoutSize) { + if (respected == 1) { + return true; + } + for (int i = 0; i < layoutSize.ncol; i++) { + if (layoutRespectMat[i * layoutSize.nrow + row] != 0) { + return true; + } + } + return false; + } + + private static boolean colRespected(int respected, int col, int[] layoutRespectMat, LayoutSize layoutSize) { + if (respected == 1) { + return true; + } + for (int i = 0; i < layoutSize.nrow; i++) { + if (layoutRespectMat[col * layoutSize.nrow + i] != 0) { + return true; + } + } + return false; + } + + private static double sumRelativeDimension(RAbstractContainer layoutItems, boolean[] relativeItems, ViewPortContext parentVPCtx, GridDevice device, GPar gpar, + boolean isWidth) { + UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, gpar, 1, 0); + double totalWidth = 0; + for (int i = 0; i < relativeItems.length; i++) { + if (relativeItems[i]) { + totalWidth += Unit.convertDimension(layoutItems, i, layoutModeCtx, isWidth); + } + } + return totalWidth; + } + + private static double getReducedDimension(RAbstractContainer layoutItems, double[] npcItems, boolean[] relativeItems, double initialSize, UnitConversionContext conversionCtx, + boolean isWidth) { + double reducedSize = initialSize; + for (int i = 0; i < npcItems.length; i++) { + boolean currIsRel = Unit.isRelativeUnit(GridContext.getContext(), layoutItems, i); + relativeItems[i] = currIsRel; + if (!currIsRel) { + npcItems[i] = Unit.convertDimension(layoutItems, i, conversionCtx, isWidth); + reducedSize -= npcItems[i]; + } + } + return reducedSize; + } + + private static RDoubleVector scalar(double val) { + return RDataFactory.createDoubleVectorFromScalar(val); + } + + // Note: unlike the GnuR counterpart of this method, we expect the LayoutPos to have the NULL + // positions replaced with nrow/ncol already. + private static ViewPortLocation calcViewportLocationFromLayout(LayoutPos pos, RList parentVP, Size parentSize) { + // unlike in GnuR, we maintain parent viewport widths/heights in inches like anything else + double[] widths = GridUtils.asDoubleVector(parentVP.getDataAt(ViewPort.PVP_WIDTHS)).materialize().getDataWithoutCopying(); + double[] heights = GridUtils.asDoubleVector(parentVP.getDataAt(ViewPort.PVP_HEIGHTS)).materialize().getDataWithoutCopying(); + double totalWidth = sum(widths, 0, pos.layoutSize.ncol); + double totalHeight = sum(heights, 0, pos.layoutSize.nrow); + double width = sum(widths, pos.colMin, pos.colMax - pos.colMin + 1); + double height = sum(heights, pos.rowMin, pos.rowMax - pos.rowMin + 1); + double left = parentSize.getWidth() * pos.layoutSize.hjust - totalWidth * pos.layoutSize.hjust + sum(widths, 0, pos.colMin); + double bottom = parentSize.getHeight() * pos.layoutSize.vjust + (1 - pos.layoutSize.vjust) * totalHeight - sum(heights, 0, pos.rowMax + 1); + ViewPortLocation result = new ViewPortLocation(); + result.width = newUnit(width, Unit.INCHES); + result.height = newUnit(height, Unit.INCHES); + result.x = newUnit(left, Unit.INCHES); + result.y = newUnit(bottom, Unit.INCHES); + result.hjust = result.vjust = 0; + return result; + } + + private static LayoutPos getLayoutPos(RList vp, RList parent) { + LayoutSize size = LayoutSize.fromViewPort(parent); + Object rowObj = vp.getDataAt(ViewPort.VP_VALIDLPOSROW); + int rowMin = 1; + int rowMax = size.nrow; + if (rowObj instanceof RAbstractIntVector) { + rowMin = ((RAbstractIntVector) rowObj).getDataAt(0); + rowMax = ((RAbstractIntVector) rowObj).getDataAt(1); + if (rowMin < 1 || rowMax > size.nrow) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "invalid 'layout.pos.row'"); + } + } + Object colObj = vp.getDataAt(ViewPort.VP_VALIDLPOSCOL); + int colMin = 1; + int colMax = size.ncol; + if (colObj instanceof RAbstractIntVector) { + colMin = ((RAbstractIntVector) colObj).getDataAt(0); + colMax = ((RAbstractIntVector) colObj).getDataAt(1); + if (colMin < 1 || colMax > size.ncol) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "invalid 'layout.pos.row'"); + } + } + // the indexes in LayoutPos are to be interpreted as 0-based + return new LayoutPos(colMin - 1, colMax - 1, rowMin - 1, rowMax - 1, size); + } + + private static boolean isNull(Object value) { + return value == null || value == RNull.instance; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java new file mode 100644 index 0000000000000000000000000000000000000000..a254e1c6703c7857b428ef2cb8cefbc5b18f0a86 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java @@ -0,0 +1,51 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import static com.oracle.truffle.r.library.fastrGrid.DoSetViewPort.doSetViewPort; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; + +import com.oracle.truffle.api.dsl.Specialization; +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.builtins.RBuiltinKind; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; + +/** + * On the top of what {@link DoSetViewPort} node does, this node sets the resulting view port as the + * current view port in the current {@link GridState} instance. This builtin allows us to write some + * of the grid code in R. + */ +@RBuiltin(name = ".fastr.grid.doSetViewPort", parameterNames = {"vp", "hasParent", "pushing"}, kind = RBuiltinKind.INTERNAL, behavior = RBehavior.COMPLEX) +public abstract class DoSetViewPortBuiltin extends RBuiltinNode.Arg3 { + + static { + Casts casts = new Casts(DoSetViewPortBuiltin.class); + casts.arg("vp").mustBe(RList.class); + casts.arg("hasParent").mustBe(logicalValue()).asLogicalVector().findFirst().map(toBoolean()); + casts.arg("pushing").mustBe(logicalValue()).asLogicalVector().findFirst().map(toBoolean()); + } + + @Specialization + RNull doIt(RList pushedVP, boolean hasParent, boolean pushing) { + RList vp = doSetViewPort(pushedVP, hasParent, pushing); + GridContext.getContext().getGridState().setViewPort(vp); + return RNull.instance; + } + + public static DoSetViewPortBuiltin create() { + return DoSetViewPortBuiltinNodeGen.create(); + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java new file mode 100644 index 0000000000000000000000000000000000000000..b78840d4010b45f7bd560bb8dac34d44d8c6292d --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java @@ -0,0 +1,279 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.fmax; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.fmin; +import static com.oracle.truffle.r.runtime.nmath.MathConstants.M_PI; +import static com.oracle.truffle.r.runtime.nmath.RMath.fmax2; +import static com.oracle.truffle.r.runtime.nmath.RMath.fmin2; +import static com.oracle.truffle.r.runtime.nmath.TOMS708.fabs; + +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.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; + +/** + * Contains static method related to edge detection for bounds calculations. + */ +final class EdgeDetection { + private EdgeDetection() { + // only static members + } + + /** + * Do two lines intersect? Algorithm from Paul Bourke + * (http://www.swin.edu.au/astronomy/pbourke/geometry/lineline2d/index.html) + */ + private static boolean linesIntersect(double x1, double x2, double x3, double x4, + double y1, double y2, double y3, double y4) { + double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1); + double ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)); + // If the lines are parallel ... + if (denom == 0) { + // If the lines are coincident ... + if (ua == 0) { + // If the lines are vertical ... + if (x1 == x2) { + // Compare y-values + if (!((y1 < y3 && fmax2(y1, y2) < fmin2(y3, y4)) || (y3 < y1 && fmax2(y3, y4) < fmin2(y1, y2)))) { + return true; + } + } else { + // Compare x-values + if (!((x1 < x3 && fmax2(x1, x2) < fmin2(x3, x4)) || (x3 < x1 && fmax2(x3, x4) < fmin2(x1, x2)))) { + return true; + } + } + } + } else { + // ... otherwise, calculate where the lines intersect ... + double ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)); + ua = ua / denom; + ub = ub / denom; + // Check for overlap + if ((ua > 0 && ua < 1) && (ub > 0 && ub < 1)) { + return true; + } + } + return false; + } + + private static boolean edgesIntersect(double x1, double x2, double y1, double y2, Rectangle r) { + return linesIntersect(x1, x2, r.x[0], r.x[1], y1, y2, r.y[0], r.y[1]) || + linesIntersect(x1, x2, r.x[1], r.x[2], y1, y2, r.y[1], r.y[2]) || + linesIntersect(x1, x2, r.x[2], r.x[3], y1, y2, r.y[2], r.y[3]) || + linesIntersect(x1, x2, r.x[3], r.x[0], y1, y2, r.y[3], r.y[0]); + } + + static Point rectEdge(double xmin, double ymin, double xmax, double ymax, double theta) { + double xm = (xmin + xmax) / 2; + double ym = (ymin + ymax) / 2; + double dx = (xmax - xmin) / 2; + double dy = (ymax - ymin) / 2; + /* + * GNUR fixme: Special case 0 width or 0 height + */ + // Special case angles + if (theta == 0) { + return new Point(xmax, ym); + } else if (theta == 270) { + return new Point(xm, ymin); + } else if (theta == 180) { + return new Point(xmin, ym); + } else if (theta == 90) { + return new Point(xm, ymax); + } else { + double cutoff = dy / dx; + double angle = theta / 180 * M_PI; + double tanTheta = Math.tan(angle); + double cosTheta = Math.cos(angle); + double sinTheta = Math.sin(angle); + if (fabs(tanTheta) < cutoff) { /* Intersect with side */ + if (cosTheta > 0) { /* Right side */ + return new Point(xmax, ym + tanTheta * dx); + } else { /* Left side */ + return new Point(xmin, ym - tanTheta * dx); + } + } else { /* Intersect with top/bottom */ + if (sinTheta > 0) { /* Top */ + return new Point(xm + dy / tanTheta, ymax); + } else { /* Bottom */ + return new Point(xm - dy / tanTheta, ymin); + } + } + } + } + + static Point polygonEdge(double[] x, double[] y, int n, double theta) { + // centre of the polygon + double xmin = fmin(Double.MAX_VALUE, x); + double xmax = fmax(Double.MIN_VALUE, x); + double ymin = fmin(Double.MAX_VALUE, y); + double ymax = fmax(Double.MIN_VALUE, y); + double xm = (xmin + xmax) / 2; + double ym = (ymin + ymax) / 2; + + // Special case zero-width or zero-height + if (fabs(xmin - xmax) < 1e-6) { + double resultY = theta == 90 ? ymax : theta == 270 ? ymin : ym; + return new Point(xmin, resultY); + } + if (fabs(ymin - ymax) < 1e-6) { + double resultX = theta == 0 ? xmax : theta == 180 ? xmin : xm; + return new Point(resultX, ymin); + } + + /* + * Find edge that intersects line from centre at angle theta + */ + boolean found = false; + double angle = theta / 180 * M_PI; + double vangle1; + double vangle2; + int v1 = 0; + int v2 = 1; + for (int i = 0; i < n; i++) { + v1 = i; + v2 = v1 + 1; + if (v2 == n) { + v2 = 0; + } + /* + * Result of atan2 is in range -PI, PI so convert to 0, 360 to correspond to angle + */ + vangle1 = Math.atan2(y[v1] - ym, x[v1] - xm); + if (vangle1 < 0) { + vangle1 = vangle1 + 2 * M_PI; + } + vangle2 = Math.atan2(y[v2] - ym, x[v2] - xm); + if (vangle2 < 0) { + vangle2 = vangle2 + 2 * M_PI; + } + /* + * If vangle1 < vangle2 then angles are either side of 0 so check is more complicated + */ + if ((vangle1 >= vangle2 && + vangle1 >= angle && vangle2 < angle) || + (vangle1 < vangle2 && + ((vangle1 >= angle && 0 <= angle) || + (vangle2 < angle && 2 * M_PI >= angle)))) { + found = true; + break; + } + } + /* + * Find intersection point of "line from centre to bounding rect" and edge + */ + if (!found) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "polygon edge not found"); + } + double x3 = x[v1]; + double y3 = y[v1]; + double x4 = x[v2]; + double y4 = y[v2]; + Point tmp = rectEdge(xmin, ymin, xmax, ymax, theta); + double x2 = tmp.x; + double y2 = tmp.y; + double numa = ((x4 - x3) * (ym - y3) - (y4 - y3) * (xm - x3)); + double denom = ((y4 - y3) * (x2 - xm) - (x4 - x3) * (y2 - ym)); + double ua = numa / denom; + if (!Double.isFinite(ua)) { + /* + * Should only happen if lines are parallel, which shouldn't happen! Unless, perhaps the + * polygon has zero extent vertically or horizontally ... ? + */ + throw RInternalError.shouldNotReachHere("polygon edge not found (zero-width or zero-height?)"); + } + /* + * numb = ((x2 - x1)*(y1 - y3) - (y2 - y1)*(x1 - x3)); ub = numb/denom; + */ + return new Point(xm + ua * (x2 - xm), ym + ua * (y2 - ym)); + } + + public static Point hullEdge(GridContext ctx, double[] xx, double[] yy, double theta) { + RDoubleVector xVec = RDataFactory.createDoubleVector(xx, RDataFactory.COMPLETE_VECTOR); + RDoubleVector yVec = RDataFactory.createDoubleVector(yy, RDataFactory.COMPLETE_VECTOR); + Object hullObj = ctx.evalInternalRFunction("chullWrapper", xVec, yVec); + RAbstractIntVector hull = GridUtils.asIntVector(hullObj); + double[] newXX = new double[hull.getLength()]; + double[] newYY = new double[hull.getLength()]; + for (int i = 0; i < hull.getLength(); i++) { + newXX[i] = xx[hull.getDataAt(i) - 1]; + newYY[i] = yy[hull.getDataAt(i) - 1]; + } + return polygonEdge(newXX, newYY, newXX.length, theta); + } + + public static Point circleEdge(Point loc, double radius, double theta) { + double angle = theta / 180 * Math.PI; + return new Point(loc.x + radius * Math.cos(angle), loc.y + radius * Math.sin(angle)); + } + + /** + * An arbitrarily-oriented rectangle. The vertices are assumed to be in order going + * anticlockwise around the rectangle. + */ + public static final class Rectangle { + public final double[] x; + public final double[] y; + + Rectangle(Point p1, Point p2, Point p3, Point p4) { + x = new double[]{p1.x, p2.x, p3.x, p4.x}; + y = new double[]{p1.y, p2.y, p3.y, p4.y}; + } + + public boolean intersects(Rectangle r2) { + return edgesIntersect(this.x[0], this.x[1], this.y[0], this.y[1], r2) || + edgesIntersect(this.x[1], this.x[2], this.y[1], this.y[2], r2) || + edgesIntersect(this.x[2], this.x[3], this.y[2], this.y[3], r2) || + edgesIntersect(this.x[3], this.x[0], this.y[3], this.y[0], r2); + } + } + + /** + * Represents min and max value for X and Y coordinates and provides convenient methods to + * update them. + */ + public static final class Bounds { + public double minX = Double.MAX_VALUE; + public double maxX = Double.MIN_VALUE; + public double minY = Double.MAX_VALUE; + public double maxY = Double.MIN_VALUE; + + public void update(Point p) { + updateX(p.x); + updateY(p.y); + } + + public void updateX(double... values) { + minX = GridUtils.fmin(minX, values); + maxX = GridUtils.fmax(maxX, values); + } + + public void updateY(double... values) { + minY = GridUtils.fmin(minY, values); + maxY = GridUtils.fmax(maxY, values); + } + + public double getWidth() { + return maxX - minX; + } + + public double getHeight() { + return maxY - minY; + } + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..1f297581c409dd3eb1c7e4bf0c1f3cf691fefcd5 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java @@ -0,0 +1,186 @@ +/* + * 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 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.grDevices.DevCairo; +import com.oracle.truffle.r.library.fastrGrid.grDevices.DevCurr; +import com.oracle.truffle.r.library.fastrGrid.grDevices.DevHoldFlush; +import com.oracle.truffle.r.library.fastrGrid.grDevices.DevOff; +import com.oracle.truffle.r.library.fastrGrid.grDevices.InitWindowedDevice; +import com.oracle.truffle.r.library.fastrGrid.grDevices.SavePlot; +import com.oracle.truffle.r.library.fastrGrid.graphics.CPar; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.RInternalCodeBuiltinNode; +import com.oracle.truffle.r.runtime.RInternalCode; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; + +/** + * Implements the lookup for externals replaced by the FastR grid package. + */ +public final class FastRGridExternalLookup { + + private FastRGridExternalLookup() { + // only static members + } + + public static RExternalBuiltinNode lookupDotExternal(String name) { + switch (name) { + case "devholdflush": + return DevHoldFlush.create(); + case "devcur": + return new DevCurr(); + case "devoff": + return DevOff.create(); + case "PDF": + return new IgnoredGridExternal(RNull.instance); + case "devCairo": + return new DevCairo(); + default: + return null; + } + } + + public static RExternalBuiltinNode lookupDotExternal2(String name) { + switch (name) { + case "C_par": + return new CPar(); + case "savePlot": + return SavePlot.create(); + case "X11": + return new InitWindowedDevice(); + default: + return null; + } + } + + public static RExternalBuiltinNode lookupDotCall(String name) { + switch (name) { + case "L_gridDirty": + return new LGridDirty(); + case "L_initGrid": + return LInitGrid.create(); + case "L_newpage": + return new LNewPage(); + case "L_convert": + return LConvert.create(); + case "L_validUnits": + return LValidUnit.create(); + case "L_pretty": + return LPretty.create(); + + // Viewport management + case "L_upviewport": + return LUpViewPort.create(); + case "L_initViewportStack": + return new LInitViewPortStack(); + case "L_unsetviewport": + return LUnsetViewPort.create(); + case "L_setviewport": + case "L_downviewport": + case "L_downvppath": + return getExternalFastRGridBuiltinNode(name); + + // Drawing primitives + case "L_rect": + return LRect.create(); + case "L_lines": + return LLines.create(); + case "L_polygon": + return LPolygon.create(); + case "L_text": + return LText.create(); + case "L_textBounds": + return LTextBounds.create(); + case "L_segments": + return LSegments.create(); + case "L_circle": + return LCircle.create(); + case "L_points": + return LPoints.create(); + + // Bounds primitive: + case "L_rectBounds": + return LRectBounds.create(); + case "L_locnBounds": + return LLocnBounds.create(); + case "L_circleBounds": + return LCircleBounds.create(); + + // Simple grid state access + case "L_getGPar": + return new GridStateGetNode(GridState::getGpar); + case "L_setGPar": + return GridStateSetNode.create((state, val) -> state.setGpar((RList) val)); + case "L_getCurrentGrob": + return new GridStateGetNode(GridState::getCurrentGrob); + case "L_setCurrentGrob": + return GridStateSetNode.create(GridState::setCurrentGrob); + case "L_currentViewport": + return new GridStateGetNode(GridState::getViewPort); + case "L_initGPar": + return new LInitGPar(); + + // Display list stuff + case "L_getDisplayList": + return new GridStateGetNode(GridState::getDisplayList); + case "L_setDisplayList": + return GridStateSetNode.create((state, val) -> state.setDisplayList((RList) val)); + case "L_getDLindex": + return new GridStateGetNode(GridState::getDisplayListIndex); + case "L_setDLindex": + return GridStateSetNode.create((state, val) -> state.setDisplayListIndex(RRuntime.asInteger(val))); + case "L_setDLelt": + return GridStateSetNode.create(GridState::setDisplayListElement); + case "L_getDLelt": + return LGetDisplayListElement.create(); + case "L_setDLon": + return LSetDisplayListOn.create(); + case "L_getDLon": + return new GridStateGetNode(state -> RRuntime.asLogical(state.isDisplayListOn())); + case "L_getEngineDLon": + return new IgnoredGridExternal(RRuntime.LOGICAL_FALSE); + case "L_initDisplayList": + return new LInitDisplayList(); + case "L_newpagerecording": + return new IgnoredGridExternal(RNull.instance); + + default: + if (name.startsWith("L_")) { + throw RInternalError.shouldNotReachHere("Unimplemented grid external " + name); + } else { + return null; + } + } + } + + private static RExternalBuiltinNode getExternalFastRGridBuiltinNode(String name) { + return new RInternalCodeBuiltinNode(RContext.getInstance(), "grid", RInternalCode.loadSourceRelativeTo(LInitGrid.class, "fastrGrid.R"), name); + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..f826ccd696f2f509374b4b9c2b072fa9ab75957c --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java @@ -0,0 +1,364 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asString; +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.device.DrawingContext; +import com.oracle.truffle.r.library.fastrGrid.device.DrawingContextDefaults; +import com.oracle.truffle.r.library.fastrGrid.device.GridColor; +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.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +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.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +/** + * In the context of grid package, GPar is a list that contains the parameters for the drawing, like + * line style, color, etc. This class wraps the list and provides way to convert it to + * {@link DrawingContext}. First create instance of {@link GPar} and then use + * {@link #getDrawingContext(int)} to get the drawing context. Note that grid's gpar can + * theoretically contain vector as the value of some graphical parameters, in such case, when + * drawing i-th element, e.g. i-th rectangle in {@link LRect}, we should use i-th (mod length) + * element of such vector. Note that this is sort of ignored in layout calculations, where we always + * take the first element. In other words, instance of {@link GPar} represents grid's gpar where the + * graphical parameter may be vectors, whereas {@link DrawingContext} is flattened view where it is + * already determined which index is used to access the vectors. + */ +public final class GPar { + private static final int GP_FILL = 0; + private static final int GP_COL = 1; + private static final int GP_GAMMA = 2; + private static final int GP_LTY = 3; + private static final int GP_LWD = 4; + + /** + * Multiplier added to the final font size. + */ + private static final int GP_CEX = 5; + + /** + * Font size in points, however, the real font size will be this multiplied by {@link #GP_CEX}. + */ + private static final int GP_FONTSIZE = 6; + + /** + * Size of the line in terms of a multiply of "one line". The final real size of a line is + * fontsize*cex*lineheight. + */ + private static final int GP_LINEHEIGHT = 7; + /** + * In fact means font style: bold, italic, bolditalic or normal. + */ + private static final int GP_FONT = 8; + private static final int GP_FONTFAMILY = 9; + private static final int GP_ALPHA = 10; + private static final int GP_LINEEND = 11; + private static final int GP_LINEJOIN = 12; + private static final int GP_LINEMITRE = 13; + /** + * Multiplier of line width {@link #GP_LWD}. + */ + private static final int GP_LEX = 14; + + // Note: there is last slot "fontface" which is either unused at all, or only used in R code + private static final int GP_LENGTH = 16; + private static final String[] NAMES = new String[]{ + "fill", + "col", + "gamma", + "lty", + "lwd", + "cex", + "fontsize", + "lineheight", + "font", + "fontfamily", + "alpha", + "lineend", + "linejoin", + "linemitre", + "lex", + "fontface" + }; + private static final RStringVector NAMES_VECTOR = (RStringVector) RDataFactory.createStringVector(NAMES, RDataFactory.COMPLETE_VECTOR).makeSharedPermanent(); + private final RList gpar; + // majority of gpar instances contains only scalar values, for those we make sure we do not + // create a new drawing context instance for every index. + private final boolean singleDrawingCtx; + private final DrawingContext indexZeroDrawingCtx; + + public GPar(RList gpar, boolean singleDrawingCtx) { + this.gpar = gpar; + this.gpar.makeSharedPermanent(); + this.singleDrawingCtx = singleDrawingCtx; + indexZeroDrawingCtx = new GParDrawingContext(gpar, 0); + } + + public static double getCex(RList gpar) { + return asDouble(gpar.getDataAt(GP_CEX)); + } + + public static GPar create(RList gpar) { + boolean singleDrawingCtx = true; + for (int i = 0; i < gpar.getLength(); i++) { + Object item = gpar.getDataAt(i); + if (item instanceof RAbstractVector) { + singleDrawingCtx &= ((RAbstractVector) item).getLength() == 1; + } + } + return new GPar(gpar, singleDrawingCtx); + } + + public DrawingContext getDrawingContext(int cyclicIndex) { + if (singleDrawingCtx || cyclicIndex == 0) { + return indexZeroDrawingCtx; + } + return new GParDrawingContext(gpar, cyclicIndex); + } + + public static RList createNew(GridDevice device) { + Object[] data = new Object[GP_LENGTH]; + DrawingContextDefaults defaults = device.getDrawingContextDefaults(); + Arrays.fill(data, RNull.instance); + data[GP_COL] = defaults.color; + data[GP_FILL] = defaults.fillColor; + data[GP_GAMMA] = newDoubleVec(0); // Note: we do not use this parameter + data[GP_LTY] = "solid"; + data[GP_LWD] = newDoubleVec(1); + data[GP_CEX] = newDoubleVec(1); + data[GP_FONTSIZE] = newDoubleVec(16); + data[GP_LINEHEIGHT] = newDoubleVec(1.2); + data[GP_FONT] = RDataFactory.createIntVectorFromScalar(1); + data[GP_FONTFAMILY] = ""; // means default font + data[GP_ALPHA] = newDoubleVec(1); + data[GP_LINEEND] = "round"; + data[GP_LINEJOIN] = "round"; + data[GP_LINEMITRE] = newDoubleVec(10); + data[GP_LEX] = newDoubleVec(1); + RList result = RDataFactory.createList(data, NAMES_VECTOR); + result.makeSharedPermanent(); + return result; + } + + private static RAbstractDoubleVector newDoubleVec(double val) { + return RDataFactory.createDoubleVectorFromScalar(val); + } + + private static final class GParDrawingContext implements DrawingContext { + private final Object[] data; + private final int index; + + private GParDrawingContext(RList list, int index) { + data = list.getDataWithoutCopying(); + this.index = index; + } + + @Override + public byte[] getLineType() { + return convertNamedValue(data[GP_LTY], LINE_STYLES.length - 1, "line type", GParDrawingContext::lineTypeFromName, num -> LINE_STYLES[num]); + } + + @Override + public double getLineWidth() { + return asDouble(data[GP_LWD], index) * asDouble(data[GP_LEX], index); + } + + @Override + public GridLineJoin getLineJoin() { + return convertNamedValue(data[GP_LINEJOIN], GridLineJoin.LAST_VALUE, "line join", GParDrawingContext::lineJoinFromName, GridLineJoin::fromInt); + } + + @Override + public GridLineEnd getLineEnd() { + return convertNamedValue(data[GP_LINEEND], GridLineEnd.LAST_VALUE, "line end", GParDrawingContext::lineEndFromName, GridLineEnd::fromInt); + } + + @Override + public double getLineMitre() { + double value = asDouble(data[GP_LINEMITRE], index); + if (value < 1.) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Invalid line mitre."); + } + return value; + } + + @Override + public GridColor getColor() { + return getGridColor(GP_COL); + } + + @Override + public double getFontSize() { + return asDouble(data[GP_FONTSIZE], index) * asDouble(data[GP_CEX], index); + } + + @Override + public GridFontStyle getFontStyle() { + return GridFontStyle.fromInt(GridUtils.asInt(data[GP_FONT], index)); + } + + @Override + public String getFontFamily() { + return GridUtils.asString(data[GP_FONTFAMILY], index); + } + + @Override + public double getLineHeight() { + return asDouble(data[GP_LINEHEIGHT], index); + } + + @Override + public GridColor getFillColor() { + return getGridColor(GP_FILL); + } + + /** + * Converts value to given enum type using either {@code nameMapper} for String values or + * {@code valueMapper} for integer value, which is first validated to be greater or equal to + * 0 and less or equal to the {@code maxValue} parameter. If {@code nameMapper} returns + * {@code null} or integer validation fails, error with given {@code propertyName} in the + * message is thrown. + */ + public <T> T convertNamedValue(Object value, int maxValue, String propertyName, Function<String, T> nameMapper, Function<Integer, T> valueMapper) { + T result = null; + if (isStringValue(value)) { + String name = asString(value, index); + if (name != null) { + result = nameMapper.apply(name); + } + } else { + int num = getIntAtMod(value, index); + if (RRuntime.isNA(num) || num < 0 || num > maxValue) { + result = null; + } else { + result = valueMapper.apply(num); + } + } + if (result == null) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Invalid " + propertyName); + } + return result; + } + + private GridColor getGridColor(int listIndex) { + GridColor color = GridColorUtils.gridColorFromString(GridUtils.asString(data[listIndex], index)); + double alpha = asDouble(data[GP_ALPHA], index); + if (alpha != 1.) { + int newAlpha = Math.min(255, (int) (alpha * ((color.getAlpha() / 255.0) * 255))); + return new GridColor(color.getRed(), color.getGreen(), color.getBlue(), newAlpha); + } else { + return color; + } + } + + 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}; + private static final byte[] LONGDASH_LINE = new byte[]{7, 3}; + private static final byte[] TWODASH_LINE = new byte[]{2, 2, 6, 2}; + private static final byte[][] LINE_STYLES = new byte[][]{DrawingContext.GRID_LINE_BLANK, DrawingContext.GRID_LINE_SOLID, DASHED_LINE, DOTTED_LINE, DOTDASH_LINE, LONGDASH_LINE, TWODASH_LINE}; + + private static byte[] lineTypeFromName(String name) { + switch (name) { + case "solid": + return DrawingContext.GRID_LINE_SOLID; + case "dashed": + return DASHED_LINE; + case "dotted": + return DOTTED_LINE; + case "dotdashed": + return DOTDASH_LINE; + case "longdash": + return LONGDASH_LINE; + case "twodash": + return TWODASH_LINE; + case "blank": + return DrawingContext.GRID_LINE_BLANK; + } + byte[] result = new byte[name.length()]; + for (int i = 0; i < name.length(); i++) { + result[i] = (byte) Character.digit(name.charAt(i), 16); + if (result[i] == -1) { + return null; + } + } + return result; + } + + private static GridLineEnd lineEndFromName(String name) { + switch (name) { + case "round": + return GridLineEnd.ROUND; + case "butt": + return GridLineEnd.BUTT; + case "square": + return GridLineEnd.SQUARE; + default: + return null; + } + } + + private static GridLineJoin lineJoinFromName(String name) { + switch (name) { + case "round": + return GridLineJoin.ROUND; + case "mitre": + return GridLineJoin.MITRE; + case "bevel": + return GridLineJoin.BEVEL; + default: + return null; + } + } + + private static boolean isStringValue(Object lty) { + return lty instanceof String || lty instanceof RAbstractStringVector; + } + + // NA indicates error + private static int getIntAtMod(Object obj, int index) { + if (obj instanceof Integer) { + return (int) obj; + } else if (obj instanceof Double) { + return (int) ((double) obj); + } else if (!(obj instanceof RAbstractContainer)) { + return RRuntime.INT_NA; + } + + RAbstractContainer value = (RAbstractContainer) obj; + if (value.getLength() == 0) { + return RRuntime.INT_NA; + } else if (value instanceof RAbstractDoubleVector) { + double realVal = getDataAtMod((RAbstractDoubleVector) value, index); + return RRuntime.isNA(realVal) ? RRuntime.INT_NA : (int) realVal; + } else if (value instanceof RAbstractIntVector) { + return getDataAtMod((RAbstractIntVector) value, index); + } else { + return RRuntime.INT_NA; + } + } + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..939a90546e5b2cfcb1ef3155d6c352519e64fe16 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java @@ -0,0 +1,747 @@ +/* + * 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 java.util.HashMap; +import java.util.Locale; + +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 GridColorUtils() { + // only static members + } + + /** + * 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. + * The acceptable color formats are: name of known color, HTML style hex value, and HTML style + * hex value including alpha. + */ + public static GridColor gridColorFromString(String value) { + if (value.startsWith("#") && (value.length() == 7 || value.length() == 9)) { + return parseHex(value); + } + + Object result = findByName(value); + if (result == null) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Invalid color '" + value + "'."); + } + if (result instanceof String) { + return parseHex((String) result); + } + assert result instanceof GridColor : "synonyms map should only contain Strings and GridColors"; + return (GridColor) result; + } + + public static String gridColorToRString(GridColor color) { + if (color.getAlpha() == GridColor.OPAQUE_ALPHA) { + return String.format("#%02x%02x%02x", color.getRed(), color.getGreen(), color.getBlue()); + } + return String.format("#%02x%02x%02x%02x", color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); + } + + private static GridColor parseHex(String value) { + // hex format, e.g. #ffffff + int red = Integer.parseInt(value.substring(1, 3), 16); + int green = Integer.parseInt(value.substring(3, 5), 16); + int blue = Integer.parseInt(value.substring(5, 7), 16); + int alpha = GridColor.OPAQUE_ALPHA; + if (value.length() == 9) { + alpha = Integer.parseInt(value.substring(7, 9), 16); + } + return new GridColor(red, green, blue, alpha); + } + + private static Object findByName(String synonym) { + return NamesHolder.NAMES.get(normalizeColorName(synonym)); + } + + // GnuR compares the user given color name to the dictionary ignoring spaces and case. We remove + // the spaces and make it lowercase and then use normal string comparison. + private static String normalizeColorName(String synonym) { + boolean isNormalized = true; + for (int i = 0; i < synonym.length(); i++) { + char c = synonym.charAt(i); + isNormalized &= (!Character.isAlphabetic(c) || Character.isLowerCase(c)) && c != ' '; + } + return isNormalized ? synonym : synonym.replace(" ", "").toLowerCase(Locale.ROOT); + } + + private static final class NamesHolder { + private static final HashMap<String, Object> NAMES = new HashMap<>(700); + + static { + NAMES.put("transparent", GridColor.TRANSPARENT); + NAMES.put("NA", GridColor.TRANSPARENT); + NAMES.put("white", "#FFFFFF"); + NAMES.put("aliceblue", "#F0F8FF"); + NAMES.put("antiquewhite", "#FAEBD7"); + NAMES.put("antiquewhite1", "#FFEFDB"); + NAMES.put("antiquewhite2", "#EEDFCC"); + NAMES.put("antiquewhite3", "#CDC0B0"); + NAMES.put("antiquewhite4", "#8B8378"); + NAMES.put("aquamarine", "#7FFFD4"); + NAMES.put("aquamarine1", "#7FFFD4"); + NAMES.put("aquamarine2", "#76EEC6"); + NAMES.put("aquamarine3", "#66CDAA"); + NAMES.put("aquamarine4", "#458B74"); + NAMES.put("azure", "#F0FFFF"); + NAMES.put("azure1", "#F0FFFF"); + NAMES.put("azure2", "#E0EEEE"); + NAMES.put("azure3", "#C1CDCD"); + NAMES.put("azure4", "#838B8B"); + NAMES.put("beige", "#F5F5DC"); + NAMES.put("bisque", "#FFE4C4"); + NAMES.put("bisque1", "#FFE4C4"); + NAMES.put("bisque2", "#EED5B7"); + NAMES.put("bisque3", "#CDB79E"); + NAMES.put("bisque4", "#8B7D6B"); + NAMES.put("black", "#000000"); + NAMES.put("blanchedalmond", "#FFEBCD"); + NAMES.put("blue", "#0000FF"); + NAMES.put("blue1", "#0000FF"); + NAMES.put("blue2", "#0000EE"); + NAMES.put("blue3", "#0000CD"); + NAMES.put("blue4", "#00008B"); + NAMES.put("blueviolet", "#8A2BE2"); + NAMES.put("brown", "#A52A2A"); + NAMES.put("brown1", "#FF4040"); + NAMES.put("brown2", "#EE3B3B"); + NAMES.put("brown3", "#CD3333"); + NAMES.put("brown4", "#8B2323"); + NAMES.put("burlywood", "#DEB887"); + NAMES.put("burlywood1", "#FFD39B"); + NAMES.put("burlywood2", "#EEC591"); + NAMES.put("burlywood3", "#CDAA7D"); + NAMES.put("burlywood4", "#8B7355"); + NAMES.put("cadetblue", "#5F9EA0"); + NAMES.put("cadetblue1", "#98F5FF"); + NAMES.put("cadetblue2", "#8EE5EE"); + NAMES.put("cadetblue3", "#7AC5CD"); + NAMES.put("cadetblue4", "#53868B"); + NAMES.put("chartreuse", "#7FFF00"); + NAMES.put("chartreuse1", "#7FFF00"); + NAMES.put("chartreuse2", "#76EE00"); + NAMES.put("chartreuse3", "#66CD00"); + NAMES.put("chartreuse4", "#458B00"); + NAMES.put("chocolate", "#D2691E"); + NAMES.put("chocolate1", "#FF7F24"); + NAMES.put("chocolate2", "#EE7621"); + NAMES.put("chocolate3", "#CD661D"); + NAMES.put("chocolate4", "#8B4513"); + NAMES.put("coral", "#FF7F50"); + NAMES.put("coral1", "#FF7256"); + NAMES.put("coral2", "#EE6A50"); + NAMES.put("coral3", "#CD5B45"); + NAMES.put("coral4", "#8B3E2F"); + NAMES.put("cornflowerblue", "#6495ED"); + NAMES.put("cornsilk", "#FFF8DC"); + NAMES.put("cornsilk1", "#FFF8DC"); + NAMES.put("cornsilk2", "#EEE8CD"); + NAMES.put("cornsilk3", "#CDC8B1"); + NAMES.put("cornsilk4", "#8B8878"); + NAMES.put("cyan", "#00FFFF"); + NAMES.put("cyan1", "#00FFFF"); + NAMES.put("cyan2", "#00EEEE"); + NAMES.put("cyan3", "#00CDCD"); + NAMES.put("cyan4", "#008B8B"); + NAMES.put("darkblue", "#00008B"); + NAMES.put("darkcyan", "#008B8B"); + NAMES.put("darkgoldenrod", "#B8860B"); + NAMES.put("darkgoldenrod1", "#FFB90F"); + NAMES.put("darkgoldenrod2", "#EEAD0E"); + NAMES.put("darkgoldenrod3", "#CD950C"); + NAMES.put("darkgoldenrod4", "#8B6508"); + NAMES.put("darkgray", "#A9A9A9"); + NAMES.put("darkgreen", "#006400"); + NAMES.put("darkgrey", "#A9A9A9"); + NAMES.put("darkkhaki", "#BDB76B"); + NAMES.put("darkmagenta", "#8B008B"); + NAMES.put("darkolivegreen", "#556B2F"); + NAMES.put("darkolivegreen1", "#CAFF70"); + NAMES.put("darkolivegreen2", "#BCEE68"); + NAMES.put("darkolivegreen3", "#A2CD5A"); + NAMES.put("darkolivegreen4", "#6E8B3D"); + NAMES.put("darkorange", "#FF8C00"); + NAMES.put("darkorange1", "#FF7F00"); + NAMES.put("darkorange2", "#EE7600"); + NAMES.put("darkorange3", "#CD6600"); + NAMES.put("darkorange4", "#8B4500"); + NAMES.put("darkorchid", "#9932CC"); + NAMES.put("darkorchid1", "#BF3EFF"); + NAMES.put("darkorchid2", "#B23AEE"); + NAMES.put("darkorchid3", "#9A32CD"); + NAMES.put("darkorchid4", "#68228B"); + NAMES.put("darkred", "#8B0000"); + NAMES.put("darksalmon", "#E9967A"); + NAMES.put("darkseagreen", "#8FBC8F"); + NAMES.put("darkseagreen1", "#C1FFC1"); + NAMES.put("darkseagreen2", "#B4EEB4"); + NAMES.put("darkseagreen3", "#9BCD9B"); + NAMES.put("darkseagreen4", "#698B69"); + NAMES.put("darkslateblue", "#483D8B"); + NAMES.put("darkslategray", "#2F4F4F"); + NAMES.put("darkslategray1", "#97FFFF"); + NAMES.put("darkslategray2", "#8DEEEE"); + NAMES.put("darkslategray3", "#79CDCD"); + NAMES.put("darkslategray4", "#528B8B"); + NAMES.put("darkslategrey", "#2F4F4F"); + NAMES.put("darkturquoise", "#00CED1"); + NAMES.put("darkviolet", "#9400D3"); + NAMES.put("deeppink", "#FF1493"); + NAMES.put("deeppink1", "#FF1493"); + NAMES.put("deeppink2", "#EE1289"); + NAMES.put("deeppink3", "#CD1076"); + NAMES.put("deeppink4", "#8B0A50"); + NAMES.put("deepskyblue", "#00BFFF"); + NAMES.put("deepskyblue1", "#00BFFF"); + NAMES.put("deepskyblue2", "#00B2EE"); + NAMES.put("deepskyblue3", "#009ACD"); + NAMES.put("deepskyblue4", "#00688B"); + NAMES.put("dimgray", "#696969"); + NAMES.put("dimgrey", "#696969"); + NAMES.put("dodgerblue", "#1E90FF"); + NAMES.put("dodgerblue1", "#1E90FF"); + NAMES.put("dodgerblue2", "#1C86EE"); + NAMES.put("dodgerblue3", "#1874CD"); + NAMES.put("dodgerblue4", "#104E8B"); + NAMES.put("firebrick", "#B22222"); + NAMES.put("firebrick1", "#FF3030"); + NAMES.put("firebrick2", "#EE2C2C"); + NAMES.put("firebrick3", "#CD2626"); + NAMES.put("firebrick4", "#8B1A1A"); + NAMES.put("floralwhite", "#FFFAF0"); + NAMES.put("forestgreen", "#228B22"); + NAMES.put("gainsboro", "#DCDCDC"); + NAMES.put("ghostwhite", "#F8F8FF"); + NAMES.put("gold", "#FFD700"); + NAMES.put("gold1", "#FFD700"); + NAMES.put("gold2", "#EEC900"); + NAMES.put("gold3", "#CDAD00"); + NAMES.put("gold4", "#8B7500"); + NAMES.put("goldenrod", "#DAA520"); + NAMES.put("goldenrod1", "#FFC125"); + NAMES.put("goldenrod2", "#EEB422"); + NAMES.put("goldenrod3", "#CD9B1D"); + NAMES.put("goldenrod4", "#8B6914"); + NAMES.put("gray", "#BEBEBE"); + NAMES.put("gray0", "#000000"); + NAMES.put("gray1", "#030303"); + NAMES.put("gray2", "#050505"); + NAMES.put("gray3", "#080808"); + NAMES.put("gray4", "#0A0A0A"); + NAMES.put("gray5", "#0D0D0D"); + NAMES.put("gray6", "#0F0F0F"); + NAMES.put("gray7", "#121212"); + NAMES.put("gray8", "#141414"); + NAMES.put("gray9", "#171717"); + NAMES.put("gray10", "#1A1A1A"); + NAMES.put("gray11", "#1C1C1C"); + NAMES.put("gray12", "#1F1F1F"); + NAMES.put("gray13", "#212121"); + NAMES.put("gray14", "#242424"); + NAMES.put("gray15", "#262626"); + NAMES.put("gray16", "#292929"); + NAMES.put("gray17", "#2B2B2B"); + NAMES.put("gray18", "#2E2E2E"); + NAMES.put("gray19", "#303030"); + NAMES.put("gray20", "#333333"); + NAMES.put("gray21", "#363636"); + NAMES.put("gray22", "#383838"); + NAMES.put("gray23", "#3B3B3B"); + NAMES.put("gray24", "#3D3D3D"); + NAMES.put("gray25", "#404040"); + NAMES.put("gray26", "#424242"); + NAMES.put("gray27", "#454545"); + NAMES.put("gray28", "#474747"); + NAMES.put("gray29", "#4A4A4A"); + NAMES.put("gray30", "#4D4D4D"); + NAMES.put("gray31", "#4F4F4F"); + NAMES.put("gray32", "#525252"); + NAMES.put("gray33", "#545454"); + NAMES.put("gray34", "#575757"); + NAMES.put("gray35", "#595959"); + NAMES.put("gray36", "#5C5C5C"); + NAMES.put("gray37", "#5E5E5E"); + NAMES.put("gray38", "#616161"); + NAMES.put("gray39", "#636363"); + NAMES.put("gray40", "#666666"); + NAMES.put("gray41", "#696969"); + NAMES.put("gray42", "#6B6B6B"); + NAMES.put("gray43", "#6E6E6E"); + NAMES.put("gray44", "#707070"); + NAMES.put("gray45", "#737373"); + NAMES.put("gray46", "#757575"); + NAMES.put("gray47", "#787878"); + NAMES.put("gray48", "#7A7A7A"); + NAMES.put("gray49", "#7D7D7D"); + NAMES.put("gray50", "#7F7F7F"); + NAMES.put("gray51", "#828282"); + NAMES.put("gray52", "#858585"); + NAMES.put("gray53", "#878787"); + NAMES.put("gray54", "#8A8A8A"); + NAMES.put("gray55", "#8C8C8C"); + NAMES.put("gray56", "#8F8F8F"); + NAMES.put("gray57", "#919191"); + NAMES.put("gray58", "#949494"); + NAMES.put("gray59", "#969696"); + NAMES.put("gray60", "#999999"); + NAMES.put("gray61", "#9C9C9C"); + NAMES.put("gray62", "#9E9E9E"); + NAMES.put("gray63", "#A1A1A1"); + NAMES.put("gray64", "#A3A3A3"); + NAMES.put("gray65", "#A6A6A6"); + NAMES.put("gray66", "#A8A8A8"); + NAMES.put("gray67", "#ABABAB"); + NAMES.put("gray68", "#ADADAD"); + NAMES.put("gray69", "#B0B0B0"); + NAMES.put("gray70", "#B3B3B3"); + NAMES.put("gray71", "#B5B5B5"); + NAMES.put("gray72", "#B8B8B8"); + NAMES.put("gray73", "#BABABA"); + NAMES.put("gray74", "#BDBDBD"); + NAMES.put("gray75", "#BFBFBF"); + NAMES.put("gray76", "#C2C2C2"); + NAMES.put("gray77", "#C4C4C4"); + NAMES.put("gray78", "#C7C7C7"); + NAMES.put("gray79", "#C9C9C9"); + NAMES.put("gray80", "#CCCCCC"); + NAMES.put("gray81", "#CFCFCF"); + NAMES.put("gray82", "#D1D1D1"); + NAMES.put("gray83", "#D4D4D4"); + NAMES.put("gray84", "#D6D6D6"); + NAMES.put("gray85", "#D9D9D9"); + NAMES.put("gray86", "#DBDBDB"); + NAMES.put("gray87", "#DEDEDE"); + NAMES.put("gray88", "#E0E0E0"); + NAMES.put("gray89", "#E3E3E3"); + NAMES.put("gray90", "#E5E5E5"); + NAMES.put("gray91", "#E8E8E8"); + NAMES.put("gray92", "#EBEBEB"); + NAMES.put("gray93", "#EDEDED"); + NAMES.put("gray94", "#F0F0F0"); + NAMES.put("gray95", "#F2F2F2"); + NAMES.put("gray96", "#F5F5F5"); + NAMES.put("gray97", "#F7F7F7"); + NAMES.put("gray98", "#FAFAFA"); + NAMES.put("gray99", "#FCFCFC"); + NAMES.put("gray100", "#FFFFFF"); + NAMES.put("green", "#00FF00"); + NAMES.put("green1", "#00FF00"); + NAMES.put("green2", "#00EE00"); + NAMES.put("green3", "#00CD00"); + NAMES.put("green4", "#008B00"); + NAMES.put("greenyellow", "#ADFF2F"); + NAMES.put("grey", "#BEBEBE"); + NAMES.put("grey0", "#000000"); + NAMES.put("grey1", "#030303"); + NAMES.put("grey2", "#050505"); + NAMES.put("grey3", "#080808"); + NAMES.put("grey4", "#0A0A0A"); + NAMES.put("grey5", "#0D0D0D"); + NAMES.put("grey6", "#0F0F0F"); + NAMES.put("grey7", "#121212"); + NAMES.put("grey8", "#141414"); + NAMES.put("grey9", "#171717"); + NAMES.put("grey10", "#1A1A1A"); + NAMES.put("grey11", "#1C1C1C"); + NAMES.put("grey12", "#1F1F1F"); + NAMES.put("grey13", "#212121"); + NAMES.put("grey14", "#242424"); + NAMES.put("grey15", "#262626"); + NAMES.put("grey16", "#292929"); + NAMES.put("grey17", "#2B2B2B"); + NAMES.put("grey18", "#2E2E2E"); + NAMES.put("grey19", "#303030"); + NAMES.put("grey20", "#333333"); + NAMES.put("grey21", "#363636"); + NAMES.put("grey22", "#383838"); + NAMES.put("grey23", "#3B3B3B"); + NAMES.put("grey24", "#3D3D3D"); + NAMES.put("grey25", "#404040"); + NAMES.put("grey26", "#424242"); + NAMES.put("grey27", "#454545"); + NAMES.put("grey28", "#474747"); + NAMES.put("grey29", "#4A4A4A"); + NAMES.put("grey30", "#4D4D4D"); + NAMES.put("grey31", "#4F4F4F"); + NAMES.put("grey32", "#525252"); + NAMES.put("grey33", "#545454"); + NAMES.put("grey34", "#575757"); + NAMES.put("grey35", "#595959"); + NAMES.put("grey36", "#5C5C5C"); + NAMES.put("grey37", "#5E5E5E"); + NAMES.put("grey38", "#616161"); + NAMES.put("grey39", "#636363"); + NAMES.put("grey40", "#666666"); + NAMES.put("grey41", "#696969"); + NAMES.put("grey42", "#6B6B6B"); + NAMES.put("grey43", "#6E6E6E"); + NAMES.put("grey44", "#707070"); + NAMES.put("grey45", "#737373"); + NAMES.put("grey46", "#757575"); + NAMES.put("grey47", "#787878"); + NAMES.put("grey48", "#7A7A7A"); + NAMES.put("grey49", "#7D7D7D"); + NAMES.put("grey50", "#7F7F7F"); + NAMES.put("grey51", "#828282"); + NAMES.put("grey52", "#858585"); + NAMES.put("grey53", "#878787"); + NAMES.put("grey54", "#8A8A8A"); + NAMES.put("grey55", "#8C8C8C"); + NAMES.put("grey56", "#8F8F8F"); + NAMES.put("grey57", "#919191"); + NAMES.put("grey58", "#949494"); + NAMES.put("grey59", "#969696"); + NAMES.put("grey60", "#999999"); + NAMES.put("grey61", "#9C9C9C"); + NAMES.put("grey62", "#9E9E9E"); + NAMES.put("grey63", "#A1A1A1"); + NAMES.put("grey64", "#A3A3A3"); + NAMES.put("grey65", "#A6A6A6"); + NAMES.put("grey66", "#A8A8A8"); + NAMES.put("grey67", "#ABABAB"); + NAMES.put("grey68", "#ADADAD"); + NAMES.put("grey69", "#B0B0B0"); + NAMES.put("grey70", "#B3B3B3"); + NAMES.put("grey71", "#B5B5B5"); + NAMES.put("grey72", "#B8B8B8"); + NAMES.put("grey73", "#BABABA"); + NAMES.put("grey74", "#BDBDBD"); + NAMES.put("grey75", "#BFBFBF"); + NAMES.put("grey76", "#C2C2C2"); + NAMES.put("grey77", "#C4C4C4"); + NAMES.put("grey78", "#C7C7C7"); + NAMES.put("grey79", "#C9C9C9"); + NAMES.put("grey80", "#CCCCCC"); + NAMES.put("grey81", "#CFCFCF"); + NAMES.put("grey82", "#D1D1D1"); + NAMES.put("grey83", "#D4D4D4"); + NAMES.put("grey84", "#D6D6D6"); + NAMES.put("grey85", "#D9D9D9"); + NAMES.put("grey86", "#DBDBDB"); + NAMES.put("grey87", "#DEDEDE"); + NAMES.put("grey88", "#E0E0E0"); + NAMES.put("grey89", "#E3E3E3"); + NAMES.put("grey90", "#E5E5E5"); + NAMES.put("grey91", "#E8E8E8"); + NAMES.put("grey92", "#EBEBEB"); + NAMES.put("grey93", "#EDEDED"); + NAMES.put("grey94", "#F0F0F0"); + NAMES.put("grey95", "#F2F2F2"); + NAMES.put("grey96", "#F5F5F5"); + NAMES.put("grey97", "#F7F7F7"); + NAMES.put("grey98", "#FAFAFA"); + NAMES.put("grey99", "#FCFCFC"); + NAMES.put("grey100", "#FFFFFF"); + NAMES.put("honeydew", "#F0FFF0"); + NAMES.put("honeydew1", "#F0FFF0"); + NAMES.put("honeydew2", "#E0EEE0"); + NAMES.put("honeydew3", "#C1CDC1"); + NAMES.put("honeydew4", "#838B83"); + NAMES.put("hotpink", "#FF69B4"); + NAMES.put("hotpink1", "#FF6EB4"); + NAMES.put("hotpink2", "#EE6AA7"); + NAMES.put("hotpink3", "#CD6090"); + NAMES.put("hotpink4", "#8B3A62"); + NAMES.put("indianred", "#CD5C5C"); + NAMES.put("indianred1", "#FF6A6A"); + NAMES.put("indianred2", "#EE6363"); + NAMES.put("indianred3", "#CD5555"); + NAMES.put("indianred4", "#8B3A3A"); + NAMES.put("ivory", "#FFFFF0"); + NAMES.put("ivory1", "#FFFFF0"); + NAMES.put("ivory2", "#EEEEE0"); + NAMES.put("ivory3", "#CDCDC1"); + NAMES.put("ivory4", "#8B8B83"); + NAMES.put("khaki", "#F0E68C"); + NAMES.put("khaki1", "#FFF68F"); + NAMES.put("khaki2", "#EEE685"); + NAMES.put("khaki3", "#CDC673"); + NAMES.put("khaki4", "#8B864E"); + NAMES.put("lavender", "#E6E6FA"); + NAMES.put("lavenderblush", "#FFF0F5"); + NAMES.put("lavenderblush1", "#FFF0F5"); + NAMES.put("lavenderblush2", "#EEE0E5"); + NAMES.put("lavenderblush3", "#CDC1C5"); + NAMES.put("lavenderblush4", "#8B8386"); + NAMES.put("lawngreen", "#7CFC00"); + NAMES.put("lemonchiffon", "#FFFACD"); + NAMES.put("lemonchiffon1", "#FFFACD"); + NAMES.put("lemonchiffon2", "#EEE9BF"); + NAMES.put("lemonchiffon3", "#CDC9A5"); + NAMES.put("lemonchiffon4", "#8B8970"); + NAMES.put("lightblue", "#ADD8E6"); + NAMES.put("lightblue1", "#BFEFFF"); + NAMES.put("lightblue2", "#B2DFEE"); + NAMES.put("lightblue3", "#9AC0CD"); + NAMES.put("lightblue4", "#68838B"); + NAMES.put("lightcoral", "#F08080"); + NAMES.put("lightcyan", "#E0FFFF"); + NAMES.put("lightcyan1", "#E0FFFF"); + NAMES.put("lightcyan2", "#D1EEEE"); + NAMES.put("lightcyan3", "#B4CDCD"); + NAMES.put("lightcyan4", "#7A8B8B"); + NAMES.put("lightgoldenrod", "#EEDD82"); + NAMES.put("lightgoldenrod1", "#FFEC8B"); + NAMES.put("lightgoldenrod2", "#EEDC82"); + NAMES.put("lightgoldenrod3", "#CDBE70"); + NAMES.put("lightgoldenrod4", "#8B814C"); + NAMES.put("lightgoldenrodyellow", "#FAFAD2"); + NAMES.put("lightgray", "#D3D3D3"); + NAMES.put("lightgreen", "#90EE90"); + NAMES.put("lightgrey", "#D3D3D3"); + NAMES.put("lightpink", "#FFB6C1"); + NAMES.put("lightpink1", "#FFAEB9"); + NAMES.put("lightpink2", "#EEA2AD"); + NAMES.put("lightpink3", "#CD8C95"); + NAMES.put("lightpink4", "#8B5F65"); + NAMES.put("lightsalmon", "#FFA07A"); + NAMES.put("lightsalmon1", "#FFA07A"); + NAMES.put("lightsalmon2", "#EE9572"); + NAMES.put("lightsalmon3", "#CD8162"); + NAMES.put("lightsalmon4", "#8B5742"); + NAMES.put("lightseagreen", "#20B2AA"); + NAMES.put("lightskyblue", "#87CEFA"); + NAMES.put("lightskyblue1", "#B0E2FF"); + NAMES.put("lightskyblue2", "#A4D3EE"); + NAMES.put("lightskyblue3", "#8DB6CD"); + NAMES.put("lightskyblue4", "#607B8B"); + NAMES.put("lightslateblue", "#8470FF"); + NAMES.put("lightslategray", "#778899"); + NAMES.put("lightslategrey", "#778899"); + NAMES.put("lightsteelblue", "#B0C4DE"); + NAMES.put("lightsteelblue1", "#CAE1FF"); + NAMES.put("lightsteelblue2", "#BCD2EE"); + NAMES.put("lightsteelblue3", "#A2B5CD"); + NAMES.put("lightsteelblue4", "#6E7B8B"); + NAMES.put("lightyellow", "#FFFFE0"); + NAMES.put("lightyellow1", "#FFFFE0"); + NAMES.put("lightyellow2", "#EEEED1"); + NAMES.put("lightyellow3", "#CDCDB4"); + NAMES.put("lightyellow4", "#8B8B7A"); + NAMES.put("limegreen", "#32CD32"); + NAMES.put("linen", "#FAF0E6"); + NAMES.put("magenta", "#FF00FF"); + NAMES.put("magenta1", "#FF00FF"); + NAMES.put("magenta2", "#EE00EE"); + NAMES.put("magenta3", "#CD00CD"); + NAMES.put("magenta4", "#8B008B"); + NAMES.put("maroon", "#B03060"); + NAMES.put("maroon1", "#FF34B3"); + NAMES.put("maroon2", "#EE30A7"); + NAMES.put("maroon3", "#CD2990"); + NAMES.put("maroon4", "#8B1C62"); + NAMES.put("mediumaquamarine", "#66CDAA"); + NAMES.put("mediumblue", "#0000CD"); + NAMES.put("mediumorchid", "#BA55D3"); + NAMES.put("mediumorchid1", "#E066FF"); + NAMES.put("mediumorchid2", "#D15FEE"); + NAMES.put("mediumorchid3", "#B452CD"); + NAMES.put("mediumorchid4", "#7A378B"); + NAMES.put("mediumpurple", "#9370DB"); + NAMES.put("mediumpurple1", "#AB82FF"); + NAMES.put("mediumpurple2", "#9F79EE"); + NAMES.put("mediumpurple3", "#8968CD"); + NAMES.put("mediumpurple4", "#5D478B"); + NAMES.put("mediumseagreen", "#3CB371"); + NAMES.put("mediumslateblue", "#7B68EE"); + NAMES.put("mediumspringgreen", "#00FA9A"); + NAMES.put("mediumturquoise", "#48D1CC"); + NAMES.put("mediumvioletred", "#C71585"); + NAMES.put("midnightblue", "#191970"); + NAMES.put("mintcream", "#F5FFFA"); + NAMES.put("mistyrose", "#FFE4E1"); + NAMES.put("mistyrose1", "#FFE4E1"); + NAMES.put("mistyrose2", "#EED5D2"); + NAMES.put("mistyrose3", "#CDB7B5"); + NAMES.put("mistyrose4", "#8B7D7B"); + NAMES.put("moccasin", "#FFE4B5"); + NAMES.put("navajowhite", "#FFDEAD"); + NAMES.put("navajowhite1", "#FFDEAD"); + NAMES.put("navajowhite2", "#EECFA1"); + NAMES.put("navajowhite3", "#CDB38B"); + NAMES.put("navajowhite4", "#8B795E"); + NAMES.put("navy", "#000080"); + NAMES.put("navyblue", "#000080"); + NAMES.put("oldlace", "#FDF5E6"); + NAMES.put("olivedrab", "#6B8E23"); + NAMES.put("olivedrab1", "#C0FF3E"); + NAMES.put("olivedrab2", "#B3EE3A"); + NAMES.put("olivedrab3", "#9ACD32"); + NAMES.put("olivedrab4", "#698B22"); + NAMES.put("orange", "#FFA500"); + NAMES.put("orange1", "#FFA500"); + NAMES.put("orange2", "#EE9A00"); + NAMES.put("orange3", "#CD8500"); + NAMES.put("orange4", "#8B5A00"); + NAMES.put("orangered", "#FF4500"); + NAMES.put("orangered1", "#FF4500"); + NAMES.put("orangered2", "#EE4000"); + NAMES.put("orangered3", "#CD3700"); + NAMES.put("orangered4", "#8B2500"); + NAMES.put("orchid", "#DA70D6"); + NAMES.put("orchid1", "#FF83FA"); + NAMES.put("orchid2", "#EE7AE9"); + NAMES.put("orchid3", "#CD69C9"); + NAMES.put("orchid4", "#8B4789"); + NAMES.put("palegoldenrod", "#EEE8AA"); + NAMES.put("palegreen", "#98FB98"); + NAMES.put("palegreen1", "#9AFF9A"); + NAMES.put("palegreen2", "#90EE90"); + NAMES.put("palegreen3", "#7CCD7C"); + NAMES.put("palegreen4", "#548B54"); + NAMES.put("paleturquoise", "#AFEEEE"); + NAMES.put("paleturquoise1", "#BBFFFF"); + NAMES.put("paleturquoise2", "#AEEEEE"); + NAMES.put("paleturquoise3", "#96CDCD"); + NAMES.put("paleturquoise4", "#668B8B"); + NAMES.put("palevioletred", "#DB7093"); + NAMES.put("palevioletred1", "#FF82AB"); + NAMES.put("palevioletred2", "#EE799F"); + NAMES.put("palevioletred3", "#CD6889"); + NAMES.put("palevioletred4", "#8B475D"); + NAMES.put("papayawhip", "#FFEFD5"); + NAMES.put("peachpuff", "#FFDAB9"); + NAMES.put("peachpuff1", "#FFDAB9"); + NAMES.put("peachpuff2", "#EECBAD"); + NAMES.put("peachpuff3", "#CDAF95"); + NAMES.put("peachpuff4", "#8B7765"); + NAMES.put("peru", "#CD853F"); + NAMES.put("pink", "#FFC0CB"); + NAMES.put("pink1", "#FFB5C5"); + NAMES.put("pink2", "#EEA9B8"); + NAMES.put("pink3", "#CD919E"); + NAMES.put("pink4", "#8B636C"); + NAMES.put("plum", "#DDA0DD"); + NAMES.put("plum1", "#FFBBFF"); + NAMES.put("plum2", "#EEAEEE"); + NAMES.put("plum3", "#CD96CD"); + NAMES.put("plum4", "#8B668B"); + NAMES.put("powderblue", "#B0E0E6"); + NAMES.put("purple", "#A020F0"); + NAMES.put("purple1", "#9B30FF"); + NAMES.put("purple2", "#912CEE"); + NAMES.put("purple3", "#7D26CD"); + NAMES.put("purple4", "#551A8B"); + NAMES.put("red", "#FF0000"); + NAMES.put("red1", "#FF0000"); + NAMES.put("red2", "#EE0000"); + NAMES.put("red3", "#CD0000"); + NAMES.put("red4", "#8B0000"); + NAMES.put("rosybrown", "#BC8F8F"); + NAMES.put("rosybrown1", "#FFC1C1"); + NAMES.put("rosybrown2", "#EEB4B4"); + NAMES.put("rosybrown3", "#CD9B9B"); + NAMES.put("rosybrown4", "#8B6969"); + NAMES.put("royalblue", "#4169E1"); + NAMES.put("royalblue1", "#4876FF"); + NAMES.put("royalblue2", "#436EEE"); + NAMES.put("royalblue3", "#3A5FCD"); + NAMES.put("royalblue4", "#27408B"); + NAMES.put("snewData.addlebrown", "#8B4513"); + NAMES.put("salmon", "#FA8072"); + NAMES.put("salmon1", "#FF8C69"); + NAMES.put("salmon2", "#EE8262"); + NAMES.put("salmon3", "#CD7054"); + NAMES.put("salmon4", "#8B4C39"); + NAMES.put("sandybrown", "#F4A460"); + NAMES.put("seagreen", "#2E8B57"); + NAMES.put("seagreen1", "#54FF9F"); + NAMES.put("seagreen2", "#4EEE94"); + NAMES.put("seagreen3", "#43CD80"); + NAMES.put("seagreen4", "#2E8B57"); + NAMES.put("seashell", "#FFF5EE"); + NAMES.put("seashell1", "#FFF5EE"); + NAMES.put("seashell2", "#EEE5DE"); + NAMES.put("seashell3", "#CDC5BF"); + NAMES.put("seashell4", "#8B8682"); + NAMES.put("sienna", "#A0522D"); + NAMES.put("sienna1", "#FF8247"); + NAMES.put("sienna2", "#EE7942"); + NAMES.put("sienna3", "#CD6839"); + NAMES.put("sienna4", "#8B4726"); + NAMES.put("skyblue", "#87CEEB"); + NAMES.put("skyblue1", "#87CEFF"); + NAMES.put("skyblue2", "#7EC0EE"); + NAMES.put("skyblue3", "#6CA6CD"); + NAMES.put("skyblue4", "#4A708B"); + NAMES.put("slateblue", "#6A5ACD"); + NAMES.put("slateblue1", "#836FFF"); + NAMES.put("slateblue2", "#7A67EE"); + NAMES.put("slateblue3", "#6959CD"); + NAMES.put("slateblue4", "#473C8B"); + NAMES.put("slategray", "#708090"); + NAMES.put("slategray1", "#C6E2FF"); + NAMES.put("slategray2", "#B9D3EE"); + NAMES.put("slategray3", "#9FB6CD"); + NAMES.put("slategray4", "#6C7B8B"); + NAMES.put("slategrey", "#708090"); + NAMES.put("snow", "#FFFAFA"); + NAMES.put("snow1", "#FFFAFA"); + NAMES.put("snow2", "#EEE9E9"); + NAMES.put("snow3", "#CDC9C9"); + NAMES.put("snow4", "#8B8989"); + NAMES.put("springgreen", "#00FF7F"); + NAMES.put("springgreen1", "#00FF7F"); + NAMES.put("springgreen2", "#00EE76"); + NAMES.put("springgreen3", "#00CD66"); + NAMES.put("springgreen4", "#008B45"); + NAMES.put("steelblue", "#4682B4"); + NAMES.put("steelblue1", "#63B8FF"); + NAMES.put("steelblue2", "#5CACEE"); + NAMES.put("steelblue3", "#4F94CD"); + NAMES.put("steelblue4", "#36648B"); + NAMES.put("tan", "#D2B48C"); + NAMES.put("tan1", "#FFA54F"); + NAMES.put("tan2", "#EE9A49"); + NAMES.put("tan3", "#CD853F"); + NAMES.put("tan4", "#8B5A2B"); + NAMES.put("thistle", "#D8BFD8"); + NAMES.put("thistle1", "#FFE1FF"); + NAMES.put("thistle2", "#EED2EE"); + NAMES.put("thistle3", "#CDB5CD"); + NAMES.put("thistle4", "#8B7B8B"); + NAMES.put("tomato", "#FF6347"); + NAMES.put("tomato1", "#FF6347"); + NAMES.put("tomato2", "#EE5C42"); + NAMES.put("tomato3", "#CD4F39"); + NAMES.put("tomato4", "#8B3626"); + NAMES.put("turquoise", "#40E0D0"); + NAMES.put("turquoise1", "#00F5FF"); + NAMES.put("turquoise2", "#00E5EE"); + NAMES.put("turquoise3", "#00C5CD"); + NAMES.put("turquoise4", "#00868B"); + NAMES.put("violet", "#EE82EE"); + NAMES.put("violetred", "#D02090"); + NAMES.put("violetred1", "#FF3E96"); + NAMES.put("violetred2", "#EE3A8C"); + NAMES.put("violetred3", "#CD3278"); + NAMES.put("violetred4", "#8B2252"); + NAMES.put("wheat", "#F5DEB3"); + NAMES.put("wheat1", "#FFE7BA"); + NAMES.put("wheat2", "#EED8AE"); + NAMES.put("wheat3", "#CDBA96"); + NAMES.put("wheat4", "#8B7E66"); + NAMES.put("whitesmoke", "#F5F5F5"); + NAMES.put("yellow", "#FFFF00"); + NAMES.put("yellow1", "#FFFF00"); + NAMES.put("yellow2", "#EEEE00"); + NAMES.put("yellow3", "#CDCD00"); + NAMES.put("yellow4", "#8B8B00"); + NAMES.put("yellowgreen", "#9ACD32"); + } + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java new file mode 100644 index 0000000000000000000000000000000000000000..a2c92c4c538b61773a56f0198121a8525c4b4606 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java @@ -0,0 +1,144 @@ +/* + * 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.library.fastrGrid.WindowDevice.awtNotSupported; + +import java.util.ArrayList; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.r.library.fastrGrid.GridState.GridDeviceState; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice.DeviceCloseException; +import com.oracle.truffle.r.library.fastrGrid.graphics.RGridGraphicsAdapter; +import com.oracle.truffle.r.runtime.FastRConfig; +import com.oracle.truffle.r.runtime.RCaller; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.RInternalCode; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.env.REnvironment; + +/** + * Encapsulated the access to the global grid state. + */ +public final class GridContext { + private static final GridContext INSTANCE = new GridContext(); + + private RInternalCode internalCode; + private final GridState gridState = new GridState(); + /** + * This list should correspond to the names inside {@code .Devices} variable in R. + */ + private final ArrayList<DeviceAndState> devices = new ArrayList<>(2); + private int currentDeviceIdx = 0; + + private GridContext() { + devices.add(new DeviceAndState(null)); + } + + public static GridContext getContext() { + return INSTANCE; + } + + @TruffleBoundary + public GridState getGridState() { + gridState.setDeviceState(devices.get(currentDeviceIdx).state); + return gridState; + } + + public int getCurrentDeviceIndex() { + return currentDeviceIdx; + } + + public int getDevicesSize() { + return devices.size(); + } + + public GridDevice getCurrentDevice() { + assert currentDeviceIdx >= 0 : "accessing devices before they were initialized"; + return devices.get(currentDeviceIdx).device; + } + + public void setCurrentDevice(String name, GridDevice currentDevice) { + RGridGraphicsAdapter.addDevice(name); + RGridGraphicsAdapter.setCurrentDevice(name); + currentDeviceIdx = this.devices.size(); + this.devices.add(new DeviceAndState(currentDevice)); + assert devices.size() == RGridGraphicsAdapter.getDevicesCount(); + } + + public void openDefaultDevice() { + String defaultDev = RGridGraphicsAdapter.getDefaultDevice(); + if (defaultDev.equals("awt") || defaultDev.startsWith("X11")) { + if (!FastRConfig.InternalGridAwtSupport) { + throw awtNotSupported(); + } else { + setCurrentDevice(defaultDev, WindowDevice.createWindowDevice()); + } + } else { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "FastR does not support device '" + defaultDev + "'."); + } + assert devices.size() == RGridGraphicsAdapter.getDevicesCount(); + } + + public void closeDevice(int which) throws DeviceCloseException { + assert which >= 0 && which < devices.size(); + devices.get(which).device.close(); + removeDevice(which); + } + + public void removeDevice(int which) { + RGridGraphicsAdapter.removeDevice(which); + devices.remove(which); + if (currentDeviceIdx >= which) { + currentDeviceIdx--; + } + } + + public GridDevice getDevice(int index) { + return devices.get(index).device; + } + + /** + * Runs arbitrary function from 'fastrGrid.R' file and returns its result. + */ + public Object evalInternalRFunction(String functionName, Object... args) { + if (internalCode == null) { + internalCode = RInternalCode.lookup(RContext.getInstance(), "grid", RInternalCode.loadSourceRelativeTo(LInitGrid.class, "fastrGrid.R")); + } + RFunction redrawAll = internalCode.lookupFunction(functionName); + return RContext.getEngine().evalFunction(redrawAll, REnvironment.baseEnv().getFrame(), RCaller.topLevel, null, args); + } + + private static final class DeviceAndState { + final GridDevice device; + final GridDeviceState state; + + DeviceAndState(GridDevice device) { + this.device = device; + this.state = new GridDeviceState(); + } + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java new file mode 100644 index 0000000000000000000000000000000000000000..1287407d6e52f3293e7faa8d46ffa062f23af8a0 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java @@ -0,0 +1,126 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asIntVector; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext; +import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +/** + * Common code shared between {@code L_lines} and {@code L_polygon} externals. Both draw a series of + * lines, but only the later connects the last point with the first point and only the former draws + * arrows (which is not implemented yet). Note: the third parameter contains sequences + * {@code 1:max(length(x),length(y))}, where the 'length' dispatches to S3 method giving us unit + * length like {@link com.oracle.truffle.r.library.fastrGrid.Unit#getLength(RAbstractContainer)}. + * This means that we do not have to use the + * {@link com.oracle.truffle.r.library.fastrGrid.Unit#getLength(RAbstractContainer)} to get the + * length. + */ +public abstract class GridLinesNode extends Node { + public static GridLinesNode createLines() { + return new GridLinesImpl(); + } + + public static GridLinesNode createPolygon() { + return new GridLinesPolygon(); + } + + @TruffleBoundary + void execute(RAbstractVector x, RAbstractVector y, RList lengths, RList arrow) { + GridContext ctx = GridContext.getContext(); + GridDevice dev = ctx.getCurrentDevice(); + + RList currentVP = ctx.getGridState().getViewPort(); + GPar gpar = GPar.create(ctx.getGridState().getGpar()); + ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev); + ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP); + UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar); + + // Convert the list of vectors of indexes to type-safe array and calculate the max length of + // the vectors. + RAbstractIntVector[] unitIndexesList = new RAbstractIntVector[lengths.getLength()]; + int maxIndexesLen = 0; + for (int i = 0; i < lengths.getLength(); i++) { + unitIndexesList[i] = asIntVector(lengths.getDataAt(i)); + maxIndexesLen = Math.max(maxIndexesLen, unitIndexesList[i].getLength()); + } + + double[] xx = new double[maxIndexesLen + 1]; // plus one for polygons + double[] yy = new double[maxIndexesLen + 1]; + for (int unitIndexesListIdx = 0; unitIndexesListIdx < unitIndexesList.length; unitIndexesListIdx++) { + RAbstractIntVector unitIndexes = unitIndexesList[unitIndexesListIdx]; + DrawingContext drawingCtx = gpar.getDrawingContext(unitIndexesListIdx); + boolean oldIsFinite = false; + int start = 0; + int unitIndexesLen = unitIndexes.getLength(); + // following loop finds series of valid points (finite x and y values) and draws each + // such series as a polyline + for (int i = 0; i < unitIndexesLen; i++) { + int unitIndex = unitIndexes.getDataAt(i) - 1; // converting R's 1-based index + Point origLoc = Point.fromUnits(x, y, unitIndex, conversionCtx); + Point loc = TransformMatrix.transLocation(origLoc, vpTransform.transform); + xx[i] = loc.x; + yy[i] = loc.y; + boolean currIsFinite = loc.isFinite(); + boolean lastIter = i == (unitIndexesLen - 1); + if (currIsFinite && !oldIsFinite) { + start = i; // start a new series + } else if (oldIsFinite && (!currIsFinite || lastIter)) { + // draw the previous points series because + // (1) current is invalid point. Note: in (one of) the next iteration(s), the + // oldIsFinite will be false and we will update the start and start a new series + // (2) we are in the last iteration + int length = i - start; + if (currIsFinite) { + // the length includes the last point only if the point is finite + length++; + } + if (length > 1) { + drawPolylines(dev, drawingCtx, yy, xx, start, length); + if (arrow != null) { + // Can draw an arrow at the start if the points include the first point. + // Draw an arrow at the end only if this is the last series + Arrows.drawArrows(xx, yy, start, length, unitIndex, arrow, start == 0, lastIter, conversionCtx); + } + } + } + oldIsFinite = currIsFinite; + } + } + } + + abstract void drawPolylines(GridDevice dev, DrawingContext drawingCtx, double[] yy, double[] xx, int start, int length); + + private static final class GridLinesImpl extends GridLinesNode { + @Override + void drawPolylines(GridDevice dev, DrawingContext drawingCtx, double[] yy, double[] xx, int start, int length) { + dev.drawPolyLines(drawingCtx, xx, yy, start, length); + } + } + + private static final class GridLinesPolygon extends GridLinesNode { + @Override + void drawPolylines(GridDevice dev, DrawingContext drawingCtx, double[] yy, double[] xx, int start, int length) { + xx[start + length] = xx[start]; + yy[start + length] = yy[start]; + dev.drawPolygon(drawingCtx, xx, yy, start, length + 1); + } + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..63585c18374f5b8e04e6325d8730b9afa1619a1b --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java @@ -0,0 +1,166 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import java.util.function.Supplier; + +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; +import com.oracle.truffle.r.runtime.env.REnvironment; + +public final class GridState { + private REnvironment gridEnv; + private GridDeviceState devState; + + /** + * Current grob being drawn (for determining the list of grobs to search when evaluating a + * grobwidth/height unit via gPath). May be RNull or RList. + */ + private Object currentGrob; + + GridState() { + } + + <T> T runWithoutRecording(Supplier<T> code) { + boolean recording = isDisplayListOn(); + setIsDisplayListOn(false); + try { + return code.get(); + } finally { + setIsDisplayListOn(recording); + } + } + + void setDeviceState(GridDeviceState state) { + devState = state; + } + + public int getDevHoldCount() { + return devState.devHoldCount; + } + + public int setDevHoldCount(int devHoldCount) { + devState.devHoldCount = devHoldCount; + return devHoldCount; + } + + public RList getDisplayList() { + if (devState.displayList == null) { + devState.displayList = DisplayList.createInitialDisplayList(); + } + return devState.displayList; + } + + public void setDisplayList(RList newList) { + newList.makeSharedPermanent(); + devState.displayList = newList; + } + + public void setDisplayListElement(Object element) { + Object[] data = devState.displayList.getDataWithoutCopying(); + data[devState.displayListIndex] = element; + } + + public boolean isDisplayListOn() { + return devState.isDisplayListOn; + } + + public void setIsDisplayListOn(boolean flag) { + devState.isDisplayListOn = flag; + } + + public int getDisplayListIndex() { + return devState.displayListIndex; + } + + public void setDisplayListIndex(int newValue) { + devState.displayListIndex = newValue; + } + + public void init(REnvironment gridEnv) { + this.gridEnv = gridEnv; + this.currentGrob = RNull.instance; + } + + void initGPar(GridDevice currentDevice) { + devState.gpar = GPar.createNew(currentDevice); + assert devState.gpar.verify(); + } + + /** + * Returns something like a canonical gpar, or top level gpar. This is used when we need a + * context to do e.g. unit conversion, but we are in a situation that no context is available. + */ + public static GPar getInitialGPar(GridDevice device) { + return GPar.create(GPar.createNew(device)); + } + + public RList getGpar() { + assert gridEnv != null : "GridState not initialized"; + return devState.gpar; + } + + public void setGpar(RList gpar) { + assert gridEnv != null : "GridState not initialized"; + devState.gpar = gpar; + } + + /** + * Has the current device been initialized for use by grid? Note: the null device should never + * get initialized. The code initializing device should check if any device is open and if not, + * it should open the default device and initialize it. + */ + public boolean isDeviceInitialized() { + return devState.isDeviceInitialized; + } + + public void setDeviceInitialized() { + devState.isDeviceInitialized = true; + } + + public RList getViewPort() { + return devState.viewPort; + } + + public void setViewPort(RList viewPort) { + assert viewPort.verify(); + devState.viewPort = viewPort; + } + + public REnvironment getGridEnv() { + return gridEnv; + } + + public Object getCurrentGrob() { + return currentGrob; + } + + public void setCurrentGrob(Object currentGrob) { + this.currentGrob = currentGrob; + } + + public double getScale() { + return devState.scale; + } + + static final class GridDeviceState { + private boolean isDeviceInitialized = false; + private RList gpar; + private RList viewPort; + private double scale = 1; + private int devHoldCount; + private boolean isDisplayListOn = true; + private RList displayList; + private int displayListIndex = 0; + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToDoubleVectorClosure.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateGetNode.java similarity index 55% rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToDoubleVectorClosure.java rename to com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateGetNode.java index 9b1d20f62a8afb8ec19e8f8b05b962b85f86a584..d53f60c9c5da8497fe4ccc39d5b67391b476158d 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToDoubleVectorClosure.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateGetNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,24 +20,32 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.data.closures; +package com.oracle.truffle.r.library.fastrGrid; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import java.util.function.Function; -final class RIntToDoubleVectorClosure extends RToDoubleVectorClosure implements RAbstractDoubleVector { +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; - RIntToDoubleVectorClosure(RAbstractIntVector vector) { - super(vector); +/** + * Gets a specified attribute of current {@link GridState}. + */ +final class GridStateGetNode extends RExternalBuiltinNode.Arg0 { + private final Function<GridState, Object> getter; + + static { + Casts.noCasts(GridStateGetNode.class); + } + + GridStateGetNode(Function<GridState, Object> getter) { + this.getter = getter; } @Override - public double getDataAt(int index) { - int data = ((RAbstractIntVector) vector).getDataAt(index); - if (!vector.isComplete() && RRuntime.isNA(data)) { - return RRuntime.DOUBLE_NA; - } - return RRuntime.int2doubleNoCheck(data); + @TruffleBoundary + public Object execute() { + Object result = getter.apply(GridContext.getContext().getGridState()); + assert result != null; + return result; } } diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/MapNodeSampler.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateSetNode.java similarity index 50% rename from com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/MapNodeSampler.java rename to com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateSetNode.java index 079c4090a1b794021b4167a0ae747e9e5fbba406..25a798d1899c0a788e0afa86f4ff9590b6dac661 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/MapNodeSampler.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateSetNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,31 +20,36 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.nodes.unary; +package com.oracle.truffle.r.library.fastrGrid; -import com.oracle.truffle.r.nodes.casts.ArgumentMapperSampler; -import com.oracle.truffle.r.nodes.casts.CastNodeSampler; -import com.oracle.truffle.r.nodes.casts.Samples; -import com.oracle.truffle.r.nodes.casts.TypeExpr; +import java.util.function.BiConsumer; -@SuppressWarnings({"rawtypes", "unchecked"}) -public class MapNodeSampler extends CastNodeSampler<MapNode> { +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.data.RNull; - private final ArgumentMapperSampler mapFn; +/** + * Sets a specified attribute of current {@link GridState}. + */ +public final class GridStateSetNode extends RExternalBuiltinNode.Arg1 { + private final BiConsumer<GridState, Object> setter; - public MapNodeSampler(MapNode castNode) { - super(castNode); - assert castNode.getMapper() instanceof ArgumentMapperSampler; - this.mapFn = (ArgumentMapperSampler) castNode.getMapper(); + static { + Casts.noCasts(GridStateSetNode.class); } - @Override - public TypeExpr resultTypes(TypeExpr inputTypes, SamplingContext ctx) { - return mapFn.resultTypes(inputTypes); + public static GridStateSetNode create(BiConsumer<GridState, Object> setter) { + return new GridStateSetNode(setter); + } + + private GridStateSetNode(BiConsumer<GridState, Object> setter) { + this.setter = setter; } @Override - public Samples<?> collectSamples(TypeExpr inputType, Samples<?> downStreamSamples) { - return mapFn.collectSamples(downStreamSamples); + @TruffleBoundary + public Object execute(Object arg) { + setter.accept(GridContext.getContext().getGridState(), arg); + return RNull.instance; } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java new file mode 100644 index 0000000000000000000000000000000000000000..76ccd7660bc91192096e874bdd7b4e111ce98696 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java @@ -0,0 +1,252 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +/* + * 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) 2001-2015, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.fmax; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.fmin; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.getDataAtMod; +import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.multiply; +import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.transLocation; +import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.translation; +import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_TO_POINTS_FACTOR; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.library.fastrGrid.EdgeDetection.Rectangle; +import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext; +import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; + +/** + * Implements what is in the original grid code implemented by {@code gridText} function. + * + * Note: the third parameter contains sequences {@code 1:max(length(x),length(y))}, where the + * 'length' dispatches to S3 method giving us unit length like + * {@link com.oracle.truffle.r.library.fastrGrid.Unit#getLength(RAbstractContainer)}. + */ +public final class GridTextNode extends RBaseNode { + + private final ConditionProfile checkOverlapProfile = ConditionProfile.createBinaryProfile(); + private final boolean draw; + + static void addGridTextCasts(Casts casts) { + casts.arg(0).asStringVector(); + casts.arg(1).mustBe(abstractVectorValue()); + casts.arg(2).mustBe(abstractVectorValue()); + casts.arg(3).mustBe(numericValue()).asDoubleVector(); + casts.arg(4).mustBe(numericValue()).asDoubleVector(); + casts.arg(5).mustBe(numericValue()).asDoubleVector(); + } + + private GridTextNode(boolean draw) { + this.draw = draw; + } + + public static GridTextNode createDraw() { + return new GridTextNode(true); + } + + public static GridTextNode createCalculateBounds() { + return new GridTextNode(false); + } + + @TruffleBoundary + public Object gridText(RAbstractStringVector textVec, RAbstractVector x, RAbstractVector y, RAbstractDoubleVector hjustVec, RAbstractDoubleVector vjustVec, RAbstractDoubleVector rotationVec, + boolean checkOverlapIn, double theta) { + if (textVec.getLength() == 0) { + return RNull.instance; + } + + boolean checkOverlap = checkOverlapProfile.profile(checkOverlapIn); + GridContext ctx = GridContext.getContext(); + GridDevice dev = ctx.getCurrentDevice(); + + RList currentVP = ctx.getGridState().getViewPort(); + GPar gpar = GPar.create(ctx.getGridState().getGpar()); + ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev); + ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP); + UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar); + + int length = GridUtils.maxLength(x, y); + + // following variables will hold the (intermediate) results of bounds checking + int boundsCount = 0; + Point edge = null; + double xmin = Double.MAX_VALUE; + double xmax = Double.MIN_VALUE; + double ymin = Double.MAX_VALUE; + double ymax = Double.MIN_VALUE; + int ntxt = 0; // number of texts that were actually used for bounds computation + EdgeDetection.Rectangle[] bounds = null; + if (checkOverlap || !draw) { + bounds = new EdgeDetection.Rectangle[length]; + } + + for (int i = 0; i < length; i++) { + Point loc = Point.fromUnits(x, y, i, conversionCtx); + if (draw) { + // transformation not necessary for bounds calculation + loc = transLocation(loc, vpTransform.transform); + } + + String text = textVec.getDataAt(i % textVec.getLength()); + double hjust = getDataAtMod(hjustVec, i); + double vjust = getDataAtMod(vjustVec, i); + double rotation = getDataAtMod(rotationVec, i); + + // update bounds if necessary + boolean doDraw = true; + Rectangle trect = null; + if (checkOverlap || !draw) { + trect = textRect(loc, hjust, vjust, rotation, text, gpar.getDrawingContext(i), dev); + for (int j = 0; j < boundsCount; j++) { + if (trect.intersects(bounds[j])) { + doDraw = false; + break; + } + } + if (doDraw) { + bounds[boundsCount++] = trect; + } + } + + // actual drawing + if (draw && doDraw) { + text(loc.x, loc.y, text, hjust, vjust, rotation + vpTransform.rotationAngle, gpar.getDrawingContext(i), dev); + } + + // or bounds checking + if (!draw) { + if (Double.isFinite(loc.x) && Double.isFinite(loc.y)) { + xmin = fmin(xmin, trect.x); + xmax = fmax(xmax, trect.x); + ymin = fmin(ymin, trect.y); + ymax = fmax(ymax, trect.y); + double[] xxx = new double[4]; + double[] yyy = new double[4]; + for (int j = 0; j < 4; j++) { + xxx[j] = trect.x[3 - j]; + yyy[j] = trect.y[3 - j]; + } + // Calculate edgex and edgey for case where this is the only rect + edge = EdgeDetection.polygonEdge(xxx, yyy, 4, theta); + ntxt++; + } + } + } + + if (!draw && ntxt > 0) { + // If there is more than one text, just produce edge based on bounding rect of all text + if (ntxt > 1) { + // Produce edge of rect bounding all text + edge = EdgeDetection.rectEdge(xmin, ymin, xmax, ymax, theta); + } + + double scale = GridContext.getContext().getGridState().getScale(); + double[] result = new double[4]; + result[0] = edge.x / scale; + result[1] = edge.y / scale; + result[2] = (xmax - xmin) / scale; + result[3] = (ymax - ymin) / scale; + return RDataFactory.createDoubleVector(result, RDataFactory.COMPLETE_VECTOR); + } + + // NULL is OK result even for bound checking if there was no text actually "drawn", the R + // wrapper deals with NULL in such case. For actual drawing case, we should always return + // NULL + return RNull.instance; + } + + // transcribed from utils.c + + private EdgeDetection.Rectangle textRect(Point loc, double xadj, double yadj, double rotation, String text, DrawingContext drawingCtx, GridDevice device) { + // TODO: for expressions the h and w are calculated differently + double h = device.getStringHeight(drawingCtx, text); + double w = device.getStringWidth(drawingCtx, text); + + double[][] thisJustification = translation(-xadj * w, -yadj * h); + double[][] thisRotation = TransformMatrix.rotation(rotation); + double[][] transform = multiply(multiply(thisJustification, thisRotation), translation(loc.x, loc.y)); + + Point bl = transLocation(new Point(0, 0), transform); + Point br = transLocation(new Point(w, 0), transform); + Point tr = transLocation(new Point(w, h), transform); + Point tl = transLocation(new Point(0, h), transform); + return new Rectangle(bl, br, tr, tl); + } + + // transcribed from engine.c + + private void text(double x, double y, String text, double xadjIn, double yadj, double rotationDegrees, DrawingContext drawingCtx, GridDevice device) { + if (!Double.isFinite(yadj)) { + throw RInternalError.unimplemented("'exact' vertical centering, see engine.c:1700"); + } + double xadj = Double.isFinite(xadjIn) ? xadjIn : 0.5; + + double radRotation = Math.toRadians(rotationDegrees); + double cosRot = Math.cos(radRotation); + double sinRot = Math.sin(radRotation); + String[] lines = text.split("\n"); + for (int lineIdx = 0; lineIdx < lines.length; lineIdx++) { + double xoff; + double yoff; + if (lines.length == 1) { + // simplification for single line + xoff = x; + yoff = y; + } else { + yoff = (1 - yadj) * (lines.length - 1) - lineIdx; + // TODO: in the original the following formula uses "dd->dev->cra[1]" + yoff *= (drawingCtx.getFontSize() * drawingCtx.getLineHeight()) / INCH_TO_POINTS_FACTOR; + xoff = -yoff * sinRot; + yoff = yoff * cosRot; + xoff = x + xoff; + yoff = y + yoff; + } + + double xleft = xoff; + double ybottom = yoff; + // now determine bottom-left for THIS line + if (xadj != 0.0 || yadj != 0.0) { + // otherwise simply the initial values for xleft and ybottom are OK + double width = device.getStringWidth(drawingCtx, lines[lineIdx]); + double height = device.getStringHeight(drawingCtx, lines[lineIdx]); + xleft = xoff - (xadj) * width * cosRot + yadj * height * sinRot; + ybottom = yoff - (xadj) * width * sinRot - yadj * height * cosRot; + } + + device.drawString(drawingCtx, xleft, ybottom, radRotation, lines[lineIdx]); + } + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..284a98450523ea60c5e2c57de3a91fd81070ab25 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java @@ -0,0 +1,229 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +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.runtime.RError; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.data.RAttributable; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +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.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.env.REnvironment; + +final class GridUtils { + private GridUtils() { + // only static members + } + + static double justify(double coord, double size, double justification) { + // justification is supposed to be either between 0 and 1 + return coord - size * justification; + } + + /** + * Returns the amount of justification required. I.e. transforms the justification from value + * between 0 and 1 to the value within size. + */ + static double justification(double size, double justification) { + return -size * justification; + } + + static double getDataAtMod(RAbstractDoubleVector vec, int idx) { + return vec.getDataAt(idx % vec.getLength()); + } + + static int getDataAtMod(RAbstractIntVector vec, int idx) { + return vec.getDataAt(idx % vec.getLength()); + } + + @ExplodeLoop + static int maxLength(RAbstractVector... units) { + int result = 0; + for (RAbstractVector unit : units) { + result = Math.max(result, Unit.getLength(unit)); + } + return result; + } + + @ExplodeLoop + static double fmax(double firstVal, double... vals) { + double result = firstVal; + for (double val : vals) { + result = fmax2(result, val); + } + return result; + } + + @ExplodeLoop + static double fmin(double firstVal, double... vals) { + double result = firstVal; + for (double val : vals) { + result = fmin2(result, val); + } + return result; + } + + static RDoubleVector createDoubleVector(double... values) { + return RDataFactory.createDoubleVector(values, RDataFactory.COMPLETE_VECTOR); + } + + static boolean hasRClass(RAttributable obj, String clazz) { + RStringVector classAttr = obj.getClassAttr(); + if (classAttr == null) { + return false; + } + for (int i = 0; i < classAttr.getLength(); i++) { + if (classAttr.getDataAt(i).equals(clazz)) { + return true; + } + } + return false; + } + + static RList asListOrNull(Object value) { + if (value == null || value == RNull.instance) { + return null; + } + if (!(value instanceof RList)) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Expected list"); + } + return (RList) value; + } + + static RList asList(Object value) { + if (!(value instanceof RList)) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Expected list"); + } + return (RList) value; + } + + static double getDoubleAt(RAbstractVector vector, int index) { + if (vector instanceof RAbstractDoubleVector) { + return ((RAbstractDoubleVector) vector).getDataAt(index); + } else if (vector instanceof RAbstractIntVector) { + return ((RAbstractIntVector) vector).getDataAt(index); + } + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non double/integer value"); + } + + static double asDouble(Object val) { + if (val instanceof Double) { + return (double) val; + } else if (val instanceof RAbstractDoubleVector) { + if (((RAbstractDoubleVector) val).getLength() > 0) { + return ((RAbstractDoubleVector) val).getDataAt(0); + } + } else if (val instanceof Integer) { + return (int) val; + } else if (val instanceof RAbstractIntVector) { + if (((RAbstractIntVector) val).getLength() > 0) { + return ((RAbstractIntVector) val).getDataAt(0); + } + } + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non double/integer value " + val.getClass().getSimpleName()); + } + + static double asDouble(Object val, int cyclicIndex) { + if (val instanceof Double) { + return (double) val; + } else if (val instanceof RAbstractDoubleVector) { + RAbstractDoubleVector vec = (RAbstractDoubleVector) val; + if (vec.getLength() > 0) { + return vec.getDataAt(cyclicIndex % vec.getLength()); + } + } + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non double value " + val.getClass().getSimpleName()); + } + + static int asInt(Object val, int cyclicIndex) { + if (val instanceof Integer) { + return (int) val; + } else if (val instanceof RAbstractIntVector) { + RAbstractIntVector vec = (RAbstractIntVector) val; + if (vec.getLength() > 0) { + return vec.getDataAt(cyclicIndex % vec.getLength()); + } + } + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non integer value " + val.getClass().getSimpleName()); + } + + static String asString(Object val, int cyclicIndex) { + if (val instanceof String) { + return (String) val; + } else if (val instanceof RAbstractStringVector) { + RAbstractStringVector vec = (RAbstractStringVector) val; + if (vec.getLength() > 0) { + return vec.getDataAt(cyclicIndex % vec.getLength()); + } + } + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non character value " + val.getClass().getSimpleName()); + } + + static RAbstractIntVector asIntVector(Object value) { + if (value instanceof Integer) { + return RDataFactory.createIntVectorFromScalar((Integer) value); + } else if (value instanceof RAbstractIntVector) { + return (RAbstractIntVector) value; + } + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non integer value " + value.getClass().getSimpleName()); + } + + public static RAbstractDoubleVector asDoubleVector(Object obj) { + if (obj instanceof Double) { + return RDataFactory.createDoubleVectorFromScalar((Double) obj); + } else if (obj instanceof RAbstractDoubleVector) { + return (RAbstractDoubleVector) obj; + } + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non double value " + obj.getClass().getSimpleName()); + } + + static RAbstractContainer asAbstractContainer(Object value) { + if (value instanceof Integer) { + return RDataFactory.createIntVectorFromScalar((Integer) value); + } else if (value instanceof Double) { + return RDataFactory.createDoubleVectorFromScalar((Double) value); + } else if (value instanceof RAbstractContainer) { + return (RAbstractContainer) value; + } + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non abstract container type " + value.getClass().getSimpleName()); + } + + static REnvironment asEnvironment(Object value) { + if (value instanceof REnvironment) { + return (REnvironment) value; + } + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected: value is not environment " + value.getClass().getSimpleName()); + } + + static double sum(double[] values) { + return sum(values, 0, values.length); + } + + static double sum(double[] values, int from, int length) { + double result = 0; + for (int i = 0; i < length; i++) { + result += values[from + i]; + } + return result; + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToStringVectorClosure.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/IgnoredGridExternal.java similarity index 57% rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToStringVectorClosure.java rename to com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/IgnoredGridExternal.java index d7352e323f4b9f79e84f30b7f09b9330d1fa6ed2..17e5e85daea190ec92d812ff8d980bd0716c4e2a 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToStringVectorClosure.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/IgnoredGridExternal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,20 +20,28 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.data.closures; +package com.oracle.truffle.r.library.fastrGrid; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; -final class RRawToStringVectorClosure extends RToStringVectorClosure implements RAbstractStringVector { +/** + * A node for externals that we ignore, because we do not need to implement them or because they + * support features we do not implement yet, especially record/replay. + */ +final class IgnoredGridExternal extends RExternalBuiltinNode { + private final Object result; + + static { + Casts.noCasts(IgnoredGridExternal.class); + } - RRawToStringVectorClosure(RAbstractRawVector vector) { - super(vector); + IgnoredGridExternal(Object result) { + this.result = result; } @Override - public String getDataAt(int index) { - return RRuntime.rawToString(((RAbstractRawVector) vector).getDataAt(index)); + protected Object call(RArgsValuesAndNames args) { + return result; } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java new file mode 100644 index 0000000000000000000000000000000000000000..cacc0eec422c77b599c52a664d562f3de9b30abe --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java @@ -0,0 +1,65 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * 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 com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.nmath.RMath; + +public abstract class LCircle extends RExternalBuiltinNode.Arg3 { + + static { + Casts casts = new Casts(LCircle.class); + addCircleCasts(casts); + } + + static void addCircleCasts(Casts casts) { + casts.arg(0).mustBe(abstractVectorValue()); + casts.arg(1).mustBe(abstractVectorValue()); + casts.arg(2).mustBe(abstractVectorValue()); + } + + public static LCircle create() { + return LCircleNodeGen.create(); + } + + @Specialization + @TruffleBoundary + Object doCircle(RAbstractVector xVec, RAbstractVector yVec, RAbstractVector radiusVec) { + GridContext ctx = GridContext.getContext(); + GridDevice dev = ctx.getCurrentDevice(); + + RList currentVP = ctx.getGridState().getViewPort(); + GPar gpar = GPar.create(ctx.getGridState().getGpar()); + ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev); + ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP); + UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar); + + int length = GridUtils.maxLength(xVec, yVec, radiusVec); + for (int i = 0; i < length; i++) { + Size radiusSizes = Size.fromUnits(radiusVec, radiusVec, i, conversionCtx); + double radius = RMath.fmin2(radiusSizes.getWidth(), radiusSizes.getHeight()); + Point origLoc = Point.fromUnits(xVec, yVec, i, conversionCtx); + Point loc = TransformMatrix.transLocation(origLoc, vpTransform.transform); + dev.drawCircle(gpar.getDrawingContext(i), loc.x, loc.y, radius); + } + return RNull.instance; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java new file mode 100644 index 0000000000000000000000000000000000000000..bab570f2e8f38d12b1c18a07637ad57f1aae9179 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java @@ -0,0 +1,81 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * 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.numericValue; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.library.fastrGrid.EdgeDetection.Bounds; +import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.nmath.RMath; + +public abstract class LCircleBounds extends RExternalBuiltinNode.Arg4 { + + static { + Casts casts = new Casts(LCircleBounds.class); + LCircle.addCircleCasts(casts); + casts.arg(3).mustBe(numericValue()).asDoubleVector().findFirst(); + } + + public static LCircleBounds create() { + return LCircleBoundsNodeGen.create(); + } + + @Specialization + @TruffleBoundary + Object doCircle(RAbstractVector xVec, RAbstractVector yVec, RAbstractVector radiusVec, double theta) { + GridContext ctx = GridContext.getContext(); + GridDevice dev = ctx.getCurrentDevice(); + + RList currentVP = ctx.getGridState().getViewPort(); + GPar gpar = GPar.create(ctx.getGridState().getGpar()); + ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev); + ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP); + UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar); + + int length = GridUtils.maxLength(xVec, yVec, radiusVec); + Bounds bounds = new Bounds(); + int count = 0; + Point loc = null; // we remember the last position and radius + double radius = -1; + for (int i = 0; i < length; i++) { + Size radiusSizes = Size.fromUnits(radiusVec, radiusVec, i, conversionCtx); + radius = RMath.fmin2(radiusSizes.getWidth(), radiusSizes.getHeight()); + loc = Point.fromUnits(xVec, yVec, i, conversionCtx); + if (loc.isFinite() && Double.isFinite(radius)) { + bounds.updateX(loc.x - radius, loc.x + radius); + bounds.updateY(loc.y - radius, loc.y + radius); + count++; + } + } + + if (count == 0) { + return RNull.instance; + } + Point result; + assert loc != null; + if (count == 1) { + result = EdgeDetection.circleEdge(loc, radius, theta); + } else { + result = EdgeDetection.rectEdge(bounds.minX, bounds.minY, bounds.maxX, bounds.maxY, theta); + } + + double scale = ctx.getGridState().getScale(); + return GridUtils.createDoubleVector(result.x / scale, result.y / scale, bounds.getWidth() / scale, bounds.getHeight() / scale); + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java new file mode 100644 index 0000000000000000000000000000000000000000..a66bbdb689aed171f31a89dc433496f2d1d0aa28 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java @@ -0,0 +1,159 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import static com.oracle.truffle.r.library.fastrGrid.Unit.NATIVE; +import static com.oracle.truffle.r.library.fastrGrid.Unit.NPC; +import static com.oracle.truffle.r.library.fastrGrid.Unit.isArithmeticUnit; +import static com.oracle.truffle.r.library.fastrGrid.Unit.isListUnit; +import static com.oracle.truffle.r.library.fastrGrid.Unit.isSimpleUnit; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.library.fastrGrid.Unit.AxisOrDimension; +import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext; +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.RList; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +public abstract class LConvert extends RExternalBuiltinNode.Arg4 { + + static { + Casts casts = new Casts(LConvert.class); + casts.arg(0).mustBe(abstractVectorValue()); + casts.arg(1).mustBe(numericValue()).asIntegerVector(); + casts.arg(2).mustBe(numericValue()).asIntegerVector(); + casts.arg(3).mustBe(numericValue()).asIntegerVector(); + } + + public static LConvert create() { + return LConvertNodeGen.create(); + } + + @Specialization + @TruffleBoundary + Object doConvert(RAbstractVector units, RAbstractIntVector axisFromVec, RAbstractIntVector axisToVec, RAbstractIntVector unitToVec) { + + GridContext ctx = GridContext.getContext(); + GridDevice dev = ctx.getCurrentDevice(); + + RList currentVP = ctx.getGridState().getViewPort(); + GPar gpar = GPar.create(ctx.getGridState().getGpar()); + ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev); + ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP); + UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar); + + int length = Unit.getLength(units); + double[] result = new double[length]; + + RAbstractIntVector unitIds = null; + if (isSimpleUnit(units)) { + unitIds = GridUtils.asIntVector(units.getAttr(Unit.VALID_UNIT_ATTR)); + } + boolean fromUnitIsSimple = !isArithmeticUnit(units) && !isListUnit(units); + + for (int i = 0; i < length; i++) { + // scalar values used in current iteration + AxisOrDimension axisFrom = AxisOrDimension.fromInt(axisFromVec.getDataAt(i % axisFromVec.getLength())); + AxisOrDimension axisTo = AxisOrDimension.fromInt(axisToVec.getDataAt(i % axisToVec.getLength())); + boolean compatibleAxes = axisFrom.isHorizontal() == axisTo.isHorizontal(); + double vpToSize = axisTo.isHorizontal() ? vpTransform.size.getWidth() : vpTransform.size.getHeight(); + double vpFromSize = axisFrom.isHorizontal() ? vpTransform.size.getWidth() : vpTransform.size.getHeight(); + int unitTo = unitToVec.getDataAt(i % unitToVec.getLength()); + int fromUnitId = -1; // invalid, and definitely not relative unit + if (unitIds != null) { + fromUnitId = unitIds.getDataAt(i % unitIds.getLength()); + } + + // actual conversion: + // if the units are both relative, we are converting compatible axes and the vpSize for + // 'from' axis is small, we will not convert through inches, but directly to avoid + // divide by zero, but still do something useful + boolean bothRelative = isRelative(unitTo) && isRelative(fromUnitId); + boolean realativeConversion = bothRelative && fromUnitIsSimple && compatibleAxes && vpFromSize < 1e-6; + if (realativeConversion) { + // if the unit is not "unit.arithmetic" or "unit.list", it must be double vector + RAbstractDoubleVector simpleUnits = (RAbstractDoubleVector) units; + double fromValue = simpleUnits.getDataAt(i % simpleUnits.getLength()); + result[i] = transformFromNPC(tranfromToNPC(fromValue, fromUnitId, axisFrom, vpContext), unitTo, axisTo, vpContext); + } else { + double inches = toInches(units, i, axisFrom, conversionCtx); + boolean isX = axisTo.isHorizontal(); + double scalemin = isX ? vpContext.xscalemin : vpContext.yscalemin; + double scalemax = isX ? vpContext.xscalemax : vpContext.yscalemax; + result[i] = Unit.convertFromInches(inches, unitTo, vpToSize, scalemin, scalemax, axisTo.isDimension(), gpar.getDrawingContext(i)); + } + } + + return RDataFactory.createDoubleVector(result, RDataFactory.COMPLETE_VECTOR); + } + + private double toInches(RAbstractVector units, int index, AxisOrDimension axisFrom, UnitConversionContext conversionCtx) { + double inches; + if (axisFrom.isHorizontal()) { + if (axisFrom.isDimension()) { + inches = Unit.convertWidth(units, index, conversionCtx); + } else { + inches = Unit.convertX(units, index, conversionCtx); + } + } else { + if (axisFrom.isDimension()) { + inches = Unit.convertHeight(units, index, conversionCtx); + } else { + inches = Unit.convertY(units, index, conversionCtx); + } + } + return inches; + } + + private static double tranfromToNPC(double value, int fromUnitId, AxisOrDimension axisFrom, ViewPortContext vpContext) { + if (fromUnitId == Unit.NPC) { + return value; + } + assert fromUnitId == Unit.NATIVE : "relative conversion should only happen when units are NPC or NATIVE"; + boolean isX = axisFrom.isHorizontal(); + double min = isX ? vpContext.xscalemin : vpContext.yscalemin; + double max = isX ? vpContext.xscalemax : vpContext.yscalemax; + if (axisFrom.isDimension()) { + return value / (max - min); + } else { + return (value - min) / (max - min); + } + } + + private static double transformFromNPC(double value, int unitTo, AxisOrDimension axisTo, ViewPortContext vpContext) { + if (unitTo == Unit.NPC) { + return value; + } + assert unitTo == Unit.NATIVE : "relative conversion should only happen when units are NPC or NATIVE"; + boolean isX = axisTo.isHorizontal(); + double min = isX ? vpContext.xscalemin : vpContext.yscalemin; + double max = isX ? vpContext.xscalemax : vpContext.yscalemax; + if (axisTo.isDimension()) { + return value * (max - min); + } else { + return min + value * (max - min); + } + } + + // Note: this is not relative in the same sense as IsRelativeUnitNode. The later checks for + // special NULL unit used only in layouting. + private static boolean isRelative(int unitId) { + return unitId == NPC || unitId == NATIVE; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java new file mode 100644 index 0000000000000000000000000000000000000000..8d865b9172905d35b33224d962037ef465cd0134 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java @@ -0,0 +1,68 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.r.library.fastrGrid.ViewPort.InitViewPortNode; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RNull; + +/** + * {@code L_gridDirty} is external that gets called before any grid operation, this is ensured by + * routing all external calls at R level through {@code grid.Call} function, which first invokes + * {@code L_gridDirty} before invoking the requested external. LGridDirty is responsible for delayed + * initialization of the grid state and device specific grid state if the device has changed since + * the last time. + */ +final class LGridDirty extends RExternalBuiltinNode { + @Child private InitViewPortNode initViewPort = new InitViewPortNode(); + + static { + Casts.noCasts(LGridDirty.class); + } + + @Override + public Object call(VirtualFrame frame, RArgsValuesAndNames args) { + GridState gridState = GridContext.getContext().getGridState(); + if (gridState.isDeviceInitialized()) { + return RNull.instance; + } + + // the rest only takes place if the device has been changed since the last time + CompilerDirectives.transferToInterpreter(); + + // if no device has been opened yet, open the default one and make it current + if (GridContext.getContext().getCurrentDevice() == null) { + GridContext.getContext().openDefaultDevice(); + // grid state is device dependent + gridState = GridContext.getContext().getGridState(); + } + + // the current device has not been initialized yet... + GridDevice device = GridContext.getContext().getCurrentDevice(); + device.openNewPage(); + gridState.initGPar(device); + gridState.setViewPort(initViewPort.execute(frame)); + DisplayList.initDisplayList(gridState); + gridState.setDeviceInitialized(); + return RNull.instance; + } + + @Override + protected Object call(RArgsValuesAndNames args) { + assert false : "should be shadowed by the overload with frame"; + return null; + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToIntVectorClosure.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java similarity index 59% rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToIntVectorClosure.java rename to com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java index 0cc977666fed3482e8e90681a59489ccba57bd3f..f902ec8d81d92587f5cb95a95b356e22b7faf09f 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToIntVectorClosure.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,20 +20,22 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.data.closures; +package com.oracle.truffle.r.library.fastrGrid; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RNull; -final class RRawToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector { - - RRawToIntVectorClosure(RAbstractRawVector vector) { - super(vector); +final class LInitGPar extends RExternalBuiltinNode { + static { + Casts.noCasts(LInitGPar.class); } @Override - public int getDataAt(int index) { - return RRuntime.raw2int(((RAbstractRawVector) vector).getDataAt(index)); + @TruffleBoundary + protected Object call(RArgsValuesAndNames args) { + GridContext.getContext().getGridState().initGPar(GridContext.getContext().getCurrentDevice()); + return RNull.instance; } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java new file mode 100644 index 0000000000000000000000000000000000000000..74aa2a0b0d02c99dda2cb92fba9605167e7462f8 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java @@ -0,0 +1,37 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.env.REnvironment; + +public abstract class LInitGrid extends RExternalBuiltinNode.Arg1 { + static { + Casts casts = new Casts(LInitGrid.class); + casts.arg(0).mustBe(REnvironment.class); + } + + public static LInitGrid create() { + return LInitGridNodeGen.create(); + } + + @Specialization + @TruffleBoundary + public Object doEnv(REnvironment gridEnv) { + GridContext context = GridContext.getContext(); + context.getGridState().init(gridEnv); + return RNull.instance; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java new file mode 100644 index 0000000000000000000000000000000000000000..fd32959d477289aa971379d8cf54ced7a28f50a1 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java @@ -0,0 +1,37 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.r.library.fastrGrid.ViewPort.InitViewPortNode; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RNull; + +final class LInitViewPortStack extends RExternalBuiltinNode { + @Child private InitViewPortNode initViewPortNode = new InitViewPortNode(); + static { + Casts.noCasts(LInitViewPortStack.class); + } + + @Override + public Object call(VirtualFrame frame, @SuppressWarnings("unused") RArgsValuesAndNames args) { + initViewPortNode.execute(frame); + return RNull.instance; + } + + @Override + protected Object call(RArgsValuesAndNames args) { + throw RInternalError.shouldNotReachHere("shadowed by the overload with VirtualFrame"); + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java new file mode 100644 index 0000000000000000000000000000000000000000..a61208b89e4a9aa11607216511b309a4e3df0366 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java @@ -0,0 +1,59 @@ +/* + * 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.abstractVectorValue; + +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +public abstract class LLines extends RExternalBuiltinNode.Arg4 { + @Child private GridLinesNode gridLinesNode = GridLinesNode.createLines(); + + static { + Casts casts = new Casts(LLines.class); + casts.arg(0).mustBe(abstractVectorValue()); + casts.arg(1).mustBe(abstractVectorValue()); + casts.arg(2).mustBe(RList.class); + casts.arg(2).allowNull().mustBe(RList.class); + } + + public static LLines create() { + return LLinesNodeGen.create(); + } + + @Specialization + Object doLines(RAbstractVector x, RAbstractVector y, RList lengths, @SuppressWarnings("unused") RNull arrowIgnored) { + gridLinesNode.execute(x, y, lengths, null); + return RNull.instance; + } + + @Specialization + Object doLines(RAbstractVector x, RAbstractVector y, RList lengths, @SuppressWarnings("unused") RList arrow) { + gridLinesNode.execute(x, y, lengths, arrow); + return RNull.instance; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java new file mode 100644 index 0000000000000000000000000000000000000000..97536e3dd007dde16e8e70b620871acbeed8d62a --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java @@ -0,0 +1,79 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * 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.numericValue; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.library.fastrGrid.EdgeDetection.Bounds; +import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +public abstract class LLocnBounds extends RExternalBuiltinNode.Arg3 { + + static { + Casts casts = new Casts(LLocnBounds.class); + casts.arg(0).mustBe(abstractVectorValue()); + casts.arg(1).mustBe(abstractVectorValue()); + casts.arg(2).mustBe(numericValue()).asDoubleVector().findFirst(); + } + + public static LLocnBounds create() { + return LLocnBoundsNodeGen.create(); + } + + @Specialization + @TruffleBoundary + Object doBounds(RAbstractVector xVec, RAbstractVector yVec, double theta) { + GridContext ctx = GridContext.getContext(); + GridDevice dev = ctx.getCurrentDevice(); + + RList currentVP = ctx.getGridState().getViewPort(); + GPar gpar = GPar.create(ctx.getGridState().getGpar()); + ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev); + ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP); + UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar); + + int length = GridUtils.maxLength(xVec, yVec); + if (length == 0) { + return RNull.instance; + } + + double[] xx = new double[length]; + double[] yy = new double[length]; + Bounds bounds = new Bounds(); + int count = 0; + for (int i = 0; i < length; i++) { + Point loc = Point.fromUnits(xVec, yVec, i, conversionCtx); + xx[i] = loc.x; + yy[i] = loc.y; + if (loc.isFinite()) { + bounds.update(loc); + count++; + } + } + + if (count == 0) { + return RNull.instance; + } + + Point edge = EdgeDetection.hullEdge(ctx, xx, yy, theta); + double scale = ctx.getGridState().getScale(); + return GridUtils.createDoubleVector(edge.x / scale, edge.y / scale, bounds.getWidth() / scale, bounds.getHeight() / scale); + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java new file mode 100644 index 0000000000000000000000000000000000000000..1b234eda3a3fc0e7ff305cf18785e6ec77813c36 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java @@ -0,0 +1,52 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RNull; + +final class LNewPage extends RExternalBuiltinNode { + static { + Casts.noCasts(LNewPage.class); + } + + @Child private LGridDirty gridDirty = new LGridDirty(); + + @Override + public Object call(VirtualFrame frame, RArgsValuesAndNames args) { + GridDevice device = GridContext.getContext().getCurrentDevice(); + if (GridContext.getContext().getGridState().isDeviceInitialized()) { + openNewPage(device); + return RNull.instance; + } + // There are some exceptions to the rule that any external call from grid R code is + // preceded by L_gridDirty call, L_newpage is one of them. + CompilerDirectives.transferToInterpreter(); + return gridDirty.call(frame, RArgsValuesAndNames.EMPTY); + } + + @TruffleBoundary + private static void openNewPage(GridDevice device) { + device.openNewPage(); + } + + @Override + protected Object call(RArgsValuesAndNames args) { + assert false : "should be shadowed by the overload with frame"; + return null; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java new file mode 100644 index 0000000000000000000000000000000000000000..c8fa2b5c39fa1ff56e03508bc88aed71c8e018a5 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java @@ -0,0 +1,243 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2015, The R Core Team + * 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.numericValue; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext; +import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext; +import com.oracle.truffle.r.library.fastrGrid.device.GridColor; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +public abstract class LPoints extends RExternalBuiltinNode.Arg4 { + private static final double SMALL = 0.25; + private static final double RADIUS = 0.375; + private static final double SQRC = 0.88622692545275801364; /* sqrt(pi / 4) */ + private static final double DMDC = 1.25331413731550025119; /* sqrt(pi / 4) * sqrt(2) */ + private static final double TRC0 = 1.55512030155621416073; /* sqrt(4 * pi/(3 * sqrt(3))) */ + private static final double TRC1 = 1.34677368708859836060; /* TRC0 * sqrt(3) / 2 */ + private static final double TRC2 = 0.77756015077810708036; /* TRC0 / 2 */ + + static { + Casts casts = new Casts(LPoints.class); + casts.arg(0).mustBe(abstractVectorValue()); + casts.arg(1).mustBe(abstractVectorValue()); + casts.arg(2).mustBe(numericValue(), Message.GENERIC, "grid.points: pch argument not implemented for characters yet").asIntegerVector(); + casts.arg(3).mustBe(abstractVectorValue()); + } + + public static LPoints create() { + return LPointsNodeGen.create(); + } + + @Specialization + @TruffleBoundary + public Object doPoints(RAbstractVector xVec, RAbstractVector yVec, RAbstractIntVector pchVec, RAbstractVector sizeVec) { + GridContext ctx = GridContext.getContext(); + GridDevice dev = ctx.getCurrentDevice(); + + RList currentVP = ctx.getGridState().getViewPort(); + RList gparList = ctx.getGridState().getGpar(); + GPar gpar = GPar.create(gparList); + double cex = GPar.getCex(gparList); + ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev); + ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP); + UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar); + + // Note: unlike in other drawing primitives, we only consider length of x + int length = Unit.getLength(xVec); + DrawingContext initialDrawingCtx = gpar.getDrawingContext(0); + PointDrawingContext pointDrawingCtx = new PointDrawingContext(initialDrawingCtx, initialDrawingCtx.getFillColor(), initialDrawingCtx.getFillColor()); + for (int i = 0; i < length; i++) { + Point loc = TransformMatrix.transLocation(Point.fromUnits(xVec, yVec, i, conversionCtx), vpTransform.transform); + double size = Unit.convertWidth(sizeVec, i, conversionCtx); + if (loc.isFinite() && Double.isFinite(size)) { + pointDrawingCtx = pointDrawingCtx.update(gpar.getDrawingContext(i)); + pointDrawingCtx = drawSymbol(pointDrawingCtx, dev, cex, pchVec.getDataAt(i % pchVec.getLength()), size, loc.x, loc.y); + } + } + return RNull.instance; + } + + // transcribed from engine.c function GESymbol + + private PointDrawingContext drawSymbol(PointDrawingContext drawingCtx, GridDevice dev, double cex, int pch, double size, double x, double y) { + // pch 0 - 25 are interpreted as geometrical shapes, pch from ascii code of ' ' are + // interpreted as corresponding ascii character, which should be drawn + switch (pch) { + case 46: + return drawDot(drawingCtx, dev, cex, x, y); + case 1: + return drawOctahedron(drawingCtx, dev, GridColor.TRANSPARENT, size, x, y); + case 19: /* R filled circle */ + return drawFilledCircle(drawingCtx, dev, RADIUS * size, x, y); + case 20: /* R `Dot' (small circle) */ + return drawFilledCircle(drawingCtx, dev, SMALL * size, x, y); + case 21: /* circles */ + return drawCircle(drawingCtx, dev, size, x, y); + case 22: /* squares */ + return drawSquare(drawingCtx, dev, size, x, y); + case 16: + return drawOctahedron(drawingCtx, dev, drawingCtx.getWrapped().getColor(), size, x, y); + default: + throw RInternalError.unimplemented("grid.points unimplemented symbol " + pch); + } + } + + private PointDrawingContext drawFilledCircle(PointDrawingContext drawingCtxIn, GridDevice dev, double radius, double x, double y) { + PointDrawingContext drawingCtx = drawingCtxIn.update(drawingCtxIn.getWrapped().getColor(), drawingCtxIn.getWrapped().getColor()); + dev.drawCircle(drawingCtx, x, y, radius); + return drawingCtx; + } + + private PointDrawingContext drawCircle(PointDrawingContext drawingCtx, GridDevice dev, double size, double x, double y) { + double xc = RADIUS * size; + dev.drawCircle(drawingCtx, x, y, xc); + return drawingCtx; + } + + private PointDrawingContext drawSquare(PointDrawingContext drawingCtx, GridDevice dev, double size, double x, double y) { + double xc = RADIUS * SQRC * size; + double yc = RADIUS * SQRC * size; + dev.drawRect(drawingCtx, x - xc, y - yc, x + xc, y + yc, 0); + return drawingCtx; + } + + private static PointDrawingContext drawOctahedron(PointDrawingContext drawingCtxIn, GridDevice dev, GridColor fill, double size, double x, double y) { + PointDrawingContext drawingCtx = drawingCtxIn.update(drawingCtxIn.getWrapped().getColor(), fill); + dev.drawCircle(drawingCtx, x, y, RADIUS * size); + return drawingCtx; + } + + private static PointDrawingContext drawDot(PointDrawingContext drawingCtxIn, GridDevice dev, double cex, double x, double y) { + // NOTE: we are *filling* a rect with the current colour (we are not drawing the border AND + // we are not using the current fill colour) + PointDrawingContext drawingCtx = drawingCtxIn.update(GridColor.TRANSPARENT, drawingCtxIn.getWrapped().getColor()); + /* + * The idea here is to use a 0.01" square, but to be of at least one device unit in each + * direction, assuming that corresponds to pixels. That may be odd if pixels are not square, + * but only on low resolution devices where we can do nothing better. + * + * For this symbol only, size is cex (see engine.c). + * + * Prior to 2.1.0 the offsets were always 0.5. + */ + double xc = cex * 0.005; + double yc = cex * 0.005; + if (cex > 0 && xc < 0.5) { + xc = 0.5; + } + if (cex > 0 && yc < 0.5) { + yc = 0.5; + } + dev.drawRect(drawingCtx, x - xc, y - yc, x + xc, y + yc, 0); + return drawingCtx; + } + + private static final class PointDrawingContext implements DrawingContext { + private final DrawingContext inner; + private final GridColor color; + private final GridColor fillColor; + + private PointDrawingContext(DrawingContext inner, GridColor color, GridColor fillColor) { + this.inner = inner; + this.color = color; + this.fillColor = fillColor; + } + + // This allows to re-use the existing instance if it would have the same parameters. The + // assumption is that the users will actually draw many points in a row with the same + // parameters. + private PointDrawingContext update(GridColor color, GridColor fillColor) { + if (this.color.equals(color) && this.fillColor.equals(fillColor)) { + return this; + } + return new PointDrawingContext(inner, color, fillColor); + } + + private PointDrawingContext update(DrawingContext inner) { + if (this.inner == inner) { + return this; + } + return new PointDrawingContext(inner, this.color, this.fillColor); + } + + @Override + public byte[] getLineType() { + return inner.getLineType(); + } + + @Override + public double getLineWidth() { + return inner.getLineWidth(); + } + + @Override + public GridLineJoin getLineJoin() { + return inner.getLineJoin(); + } + + @Override + public GridLineEnd getLineEnd() { + return inner.getLineEnd(); + } + + @Override + public double getLineMitre() { + return inner.getLineMitre(); + } + + @Override + public GridColor getColor() { + return color; + } + + @Override + public double getFontSize() { + return inner.getFontSize(); + } + + @Override + public GridFontStyle getFontStyle() { + return inner.getFontStyle(); + } + + @Override + public String getFontFamily() { + return inner.getFontFamily(); + } + + @Override + public double getLineHeight() { + return inner.getLineHeight(); + } + + @Override + public GridColor getFillColor() { + return fillColor; + } + + private DrawingContext getWrapped() { + return inner; + } + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPolygon.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPolygon.java new file mode 100644 index 0000000000000000000000000000000000000000..a4d8a917bd2bc2387d1faa7cb8b5026ee5fb37c3 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPolygon.java @@ -0,0 +1,52 @@ +/* + * 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.abstractVectorValue; + +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +public abstract class LPolygon extends RExternalBuiltinNode.Arg3 { + @Child private GridLinesNode gridLinesNode = GridLinesNode.createPolygon(); + + static { + Casts casts = new Casts(LPolygon.class); + casts.arg(0).mustBe(abstractVectorValue()); + casts.arg(1).mustBe(abstractVectorValue()); + casts.arg(2).mustBe(RList.class); + } + + public static LPolygon create() { + return LPolygonNodeGen.create(); + } + + @Specialization + Object doLines(RAbstractVector x, RAbstractVector y, RList lengths) { + gridLinesNode.execute(x, y, lengths, null); + return RNull.instance; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPretty.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPretty.java new file mode 100644 index 0000000000000000000000000000000000000000..2d447deb2c14deb1ba1fcc1194328383ee72480f --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPretty.java @@ -0,0 +1,100 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * 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.numericValue; +import static com.oracle.truffle.r.runtime.nmath.TOMS708.fabs; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.PrettyIntevals; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; + +public abstract class LPretty extends RExternalBuiltinNode.Arg1 { + static { + Casts casts = new Casts(LPretty.class); + casts.arg(0).mustBe(numericValue()).asDoubleVector(); + } + + public static LPretty create() { + return LPrettyNodeGen.create(); + } + + @Specialization + protected Object doPretty(RAbstractDoubleVector scale) { + double min = scale.getLength() > 0 ? scale.getDataAt(0) : 0; + double max = scale.getLength() > 1 ? scale.getDataAt(1) : 0; + boolean swap = max < min; + if (swap) { + min = max; + max = scale.getDataAt(0); + } + + if (Double.isInfinite(min) || Double.isInfinite(max)) { + CompilerDirectives.transferToInterpreter(); + throw error(Message.GENERIC, String.format("infinite axis extents [GEPretty(%g,%g,5)]", min, max)); + } + + double[] ns = new double[]{min}; + double[] nu = new double[]{max}; + int[] ndiv = new int[]{5}; + double unit = PrettyIntevals.pretty(getErrorContext(), ns, nu, new int[]{5}, 1, 0.25, new double[]{.8, 1.7}, 2, false); + + if (nu[0] >= ns[0] + 1) { + if (ns[0] * unit < min - 1e-7 * unit) { + ns[0]++; + } + if (nu[0] > ns[0] + 1 && nu[0] * unit > max + 1e-7 * unit) { + nu[0]--; + } + ndiv[0] = (int) (nu[0] - ns[0]); + } + min = ns[0] * unit; + max = nu[0] * unit; + + if (swap) { + double temp = min; + min = max; + max = temp; + } + return createAtVector(min, max, ndiv[0]); + } + + private static RAbstractDoubleVector createAtVector(double axp0, double axp1, double axp2) { + /* + * Create an 'at = ...' vector for axis(.) i.e., the vector of tick mark locations, when + * none has been specified (= default). + * + * axp[0:2] = (x1, x2, nInt), where x1..x2 are the extreme tick marks {unless in log case, + * where nInt \in {1,2,3 ; -1,-2,....} and the `nint' argument is used *instead*.} The + * resulting REAL vector must have length >= 1, ideally >= 2 + * + * FastR Notes: we only implement case where logflag == false. + */ + /* --- linear axis --- Only use axp[] arg. */ + int n = (int) (fabs(axp2) + 0.25); /* >= 0 */ + int dn = Math.max(1, n); + double rng = axp1 - axp0; + double small = fabs(rng) / (100. * dn); + double[] at = new double[n + 1]; + for (int i = 0; i <= n; i++) { + at[i] = axp0 + ((double) i / dn) * rng; + if (fabs(at[i]) < small) { + at[i] = 0; + } + } + return RDataFactory.createDoubleVector(at, RDataFactory.COMPLETE_VECTOR); + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java new file mode 100644 index 0000000000000000000000000000000000000000..1d2ce1bdb67b9d8213ca2a9a7481feddbaf14e0f --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java @@ -0,0 +1,70 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.getDataAtMod; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +public abstract class LRect extends RExternalBuiltinNode.Arg6 { + + static { + Casts casts = new Casts(LRect.class); + addRectCasts(casts); + } + + static void addRectCasts(Casts casts) { + casts.arg(0).mustBe(abstractVectorValue()); + casts.arg(1).mustBe(abstractVectorValue()); + casts.arg(2).mustBe(abstractVectorValue()); + casts.arg(3).mustBe(abstractVectorValue()); + casts.arg(4).mustBe(numericValue()).asDoubleVector(); + casts.arg(5).mustBe(numericValue()).asDoubleVector(); + } + + public static LRect create() { + return LRectNodeGen.create(); + } + + @Specialization + @TruffleBoundary + public Object execute(RAbstractVector xVec, RAbstractVector yVec, RAbstractVector wVec, RAbstractVector hVec, RAbstractDoubleVector hjust, RAbstractDoubleVector vjust) { + GridContext ctx = GridContext.getContext(); + GridDevice dev = ctx.getCurrentDevice(); + + RList currentVP = ctx.getGridState().getViewPort(); + GPar gpar = GPar.create(ctx.getGridState().getGpar()); + ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev); + ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP); + UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar); + + int length = GridUtils.maxLength(xVec, yVec, wVec, hVec); + for (int i = 0; i < length; i++) { + Size size = Size.fromUnits(wVec, hVec, i, conversionCtx); + Point origLoc = Point.fromUnits(xVec, yVec, i, conversionCtx); + Point transLoc = TransformMatrix.transLocation(origLoc, vpTransform.transform); + Point loc = transLoc.justify(size, getDataAtMod(hjust, i), getDataAtMod(vjust, i)); + dev.drawRect(gpar.getDrawingContext(i), loc.x, loc.y, size.getWidth(), size.getHeight(), Math.toRadians(vpTransform.rotationAngle)); + } + return RNull.instance; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java new file mode 100644 index 0000000000000000000000000000000000000000..2aff9d698f78f0ef53b1e3359ea9d483212146ce --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java @@ -0,0 +1,77 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import static com.oracle.truffle.r.library.fastrGrid.EdgeDetection.rectEdge; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.getDataAtMod; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.library.fastrGrid.EdgeDetection.Bounds; +import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext; +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.RList; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +public abstract class LRectBounds extends RExternalBuiltinNode.Arg7 { + + static { + Casts casts = new Casts(LRectBounds.class); + LRect.addRectCasts(casts); + casts.arg(6).mustBe(numericValue()).asDoubleVector().findFirst(); + } + + public static LRectBounds create() { + return LRectBoundsNodeGen.create(); + } + + @Specialization + @TruffleBoundary + Object execute(RAbstractVector xVec, RAbstractVector yVec, RAbstractVector wVec, RAbstractVector hVec, RAbstractDoubleVector hjust, RAbstractDoubleVector vjust, double theta) { + GridContext ctx = GridContext.getContext(); + GridDevice dev = ctx.getCurrentDevice(); + + RList currentVP = ctx.getGridState().getViewPort(); + GPar gpar = GPar.create(ctx.getGridState().getGpar()); + ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev); + ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP); + UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar); + + int length = GridUtils.maxLength(xVec, yVec, wVec, hVec); + Bounds bounds = new Bounds(); + int nrect = 0; + for (int i = 0; i < length; i++) { + Size size = Size.fromUnits(wVec, hVec, i, conversionCtx); + Point origLoc = Point.fromUnits(xVec, yVec, i, conversionCtx); + // just calculate the bounds, no transformation necessary + Point loc = origLoc.justify(size, getDataAtMod(hjust, i), getDataAtMod(vjust, i)); + if (size.isFinite() && loc.isFinite()) { + bounds.updateX(loc.x, loc.x + size.getWidth()); + bounds.updateY(loc.y, loc.y + size.getHeight()); + nrect++; + } + } + + if (nrect == 0) { + return RNull.instance; + } + + Point edge = rectEdge(bounds.minX, bounds.minY, bounds.maxX, bounds.maxY, theta); + double scale = ctx.getGridState().getScale(); + return RDataFactory.createDoubleVector(new double[]{edge.x / scale, edge.y / scale, bounds.getWidth() / scale, bounds.getHeight() / scale}, RDataFactory.COMPLETE_VECTOR); + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java new file mode 100644 index 0000000000000000000000000000000000000000..2c384f0488e7801d38ebc4baa8c0c9d309bc5289 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java @@ -0,0 +1,80 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * 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 com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +/** + * Gets (vectors of) 4 coordinates (two points) and draws a line between them, unlike {@link LLines} + * which gets a vector of points and connects them all. + */ +public abstract class LSegments extends RExternalBuiltinNode.Arg5 { + static { + Casts casts = new Casts(LSegments.class); + casts.arg(0).mustBe(abstractVectorValue()); + casts.arg(1).mustBe(abstractVectorValue()); + casts.arg(2).mustBe(abstractVectorValue()); + casts.arg(3).mustBe(abstractVectorValue()); + casts.arg(4).allowNull().mustBe(RList.class); + } + + public static LSegments create() { + return LSegmentsNodeGen.create(); + } + + @Specialization + Object doSegments(RAbstractVector x0, RAbstractVector y0, RAbstractVector x1, RAbstractVector y1, @SuppressWarnings("unused") RNull arrow) { + return doSegments(x0, y0, x1, y1, (RList) null); + } + + @Specialization + @TruffleBoundary + Object doSegments(RAbstractVector x0, RAbstractVector y0, RAbstractVector x1, RAbstractVector y1, RList arrow) { + GridContext ctx = GridContext.getContext(); + GridDevice dev = ctx.getCurrentDevice(); + + RList currentVP = ctx.getGridState().getViewPort(); + GPar gpar = GPar.create(ctx.getGridState().getGpar()); + ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev); + ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP); + UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar); + + int length = GridUtils.maxLength(x0, y0, x1, y1); + double[] xx = new double[2]; + double[] yy = new double[2]; + for (int i = 0; i < length; i++) { + Point loc1 = TransformMatrix.transLocation(Point.fromUnits(x0, y0, i, conversionCtx), vpTransform.transform); + Point loc2 = TransformMatrix.transLocation(Point.fromUnits(x1, y1, i, conversionCtx), vpTransform.transform); + if (!loc1.isFinite() || !loc2.isFinite()) { + continue; + } + xx[0] = loc1.x; + xx[1] = loc2.x; + yy[0] = loc1.y; + yy[1] = loc2.y; + dev.drawPolyLines(gpar.getDrawingContext(i), xx, yy, 0, 2); + if (arrow != null) { + Arrows.drawArrows(xx, yy, 0, 2, i, arrow, true, true, conversionCtx); + } + } + return RNull.instance; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LText.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LText.java new file mode 100644 index 0000000000000000000000000000000000000000..c22cf068da8963e2ec89eaa5ba5c1778029b4705 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LText.java @@ -0,0 +1,55 @@ +/* + * 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.library.fastrGrid.GridTextNode.addGridTextCasts; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; + +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.nodes.NodeCost; +import com.oracle.truffle.api.nodes.NodeInfo; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +@NodeInfo(cost = NodeCost.NONE) +public abstract class LText extends RExternalBuiltinNode.Arg7 { + static { + Casts casts = new Casts(LText.class); + addGridTextCasts(casts); + casts.arg(6).mustBe(logicalValue()).asLogicalVector().findFirst().map(toBoolean()); + } + + public static LText create() { + return LTextNodeGen.create(); + } + + @Specialization + Object drawText(RAbstractStringVector text, RAbstractVector x, RAbstractVector y, RAbstractDoubleVector hjust, RAbstractDoubleVector vjust, RAbstractDoubleVector rotation, boolean checkOverlap, + @Cached("createDraw()") GridTextNode gridText) { + return gridText.gridText(text, x, y, hjust, vjust, rotation, checkOverlap, 0); + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LTextBounds.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LTextBounds.java new file mode 100644 index 0000000000000000000000000000000000000000..fa1ec97d723de0ecc9ce446b956b9307558f32a5 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LTextBounds.java @@ -0,0 +1,56 @@ +/* + * 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.library.fastrGrid.GridTextNode.addGridTextCasts; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; + +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.nodes.NodeCost; +import com.oracle.truffle.api.nodes.NodeInfo; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +@NodeInfo(cost = NodeCost.NONE) +public abstract class LTextBounds extends RExternalBuiltinNode.Arg7 { + static { + Casts casts = new Casts(LTextBounds.class); + addGridTextCasts(casts); + casts.arg(6).returnIf(missingValue().or(nullValue()), constant(0)).asDoubleVector().findFirst(); + } + + public static LTextBounds create() { + return LTextBoundsNodeGen.create(); + } + + @Specialization + public Object textBounds(RAbstractStringVector text, RAbstractVector x, RAbstractVector y, RAbstractDoubleVector hjust, RAbstractDoubleVector vjust, RAbstractDoubleVector rotation, double theta, + @Cached("createCalculateBounds()") GridTextNode gridText) { + return gridText.gridText(text, x, y, hjust, vjust, rotation, false, theta); + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java new file mode 100644 index 0000000000000000000000000000000000000000..f8fb9b0e6da3f6c0989ea781ed35fca95360d790 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java @@ -0,0 +1,88 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asList; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asListOrNull; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; + +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.RError.Message; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.env.REnvironment.PutException; + +public abstract class LUnsetViewPort extends RExternalBuiltinNode.Arg1 { + static { + Casts casts = new Casts(LUnsetViewPort.class); + casts.arg(0).mustBe(numericValue()).asIntegerVector().findFirst(); + } + + public static LUnsetViewPort create() { + return LUnsetViewPortNodeGen.create(); + } + + @Specialization + @TruffleBoundary + Object unsetViewPort(int n) { + GridContext ctx = GridContext.getContext(); + GridState gridState = ctx.getGridState(); + + // go n-steps up the view-port tree + RList gvp = gridState.getViewPort(); + RList newVp = gvp; + for (int i = 0; i < n; i++) { + gvp = newVp; + newVp = asListOrNull(gvp.getDataAt(ViewPort.PVP_PARENT)); + if (newVp == null) { + throw error(Message.GENERIC, "cannot pop the top-level viewport ('grid' and 'graphics' output mixed?)"); + } + } + + // gvp will be removed, newVp will be the new view-port + // first update children of newVp -> remove gvp + REnvironment children = (REnvironment) newVp.getDataAt(ViewPort.PVP_CHILDREN); + String gvpName = RRuntime.asString(gvp.getDataAt(ViewPort.VP_NAME)); + safeRemoveFromEnv(children, gvpName); + + // update newVp transform etc. because it will be the current vp, it has to be up to date + GridDevice device = ctx.getCurrentDevice(); + if (ViewPort.updateDeviceSizeInVP(newVp, device)) { + // Note: like in other places calling this, why incremental == true, given that the + // device has changed? Don't we want to recalculate the whole tree? + DoSetViewPort.calcViewportTransform(newVp, newVp.getDataAt(ViewPort.PVP_PARENT), true, device, GridState.getInitialGPar(device)); + } + + gridState.setGpar(asList(newVp.getDataAt(ViewPort.PVP_GPAR))); + + // TODO: clipping + gridState.setViewPort(newVp); + + // remove the parent link from the old viewport + gvp.setDataAt(gvp.getInternalStore(), ViewPort.PVP_PARENT, RNull.instance); + return RNull.instance; + } + + private void safeRemoveFromEnv(REnvironment children, String gvpName) { + try { + children.rm(gvpName); + } catch (PutException e) { + throw RInternalError.shouldNotReachHere("Cannot update view-port children environment"); + } + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUpViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUpViewPort.java new file mode 100644 index 0000000000000000000000000000000000000000..bee678f784f0b604ed3810c3880b7dd5495d78f6 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUpViewPort.java @@ -0,0 +1,50 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * 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.gte; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; +import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder; + +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.nodes.unary.CastNode; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; + +public abstract class LUpViewPort extends RExternalBuiltinNode.Arg1 { + @Child private CastNode castParentToViewPort = newCastBuilder().mustBe(RList.class, Message.GENERIC, "cannot pop the top-level viewport ('grid' and 'graphics' output mixed?)").buildCastNode(); + + static { + Casts casts = new Casts(LUpViewPort.class); + casts.arg(0).mustBe(numericValue()).asIntegerVector().findFirst(1).mustBe(gte(1)); + } + + public static LUpViewPort create() { + return LUpViewPortNodeGen.create(); + } + + @Specialization + Object upViewPort(int n) { + GridState gridState = GridContext.getContext().getGridState(); + RList newViewPort = gridState.getViewPort(); + for (int i = 0; i < n; i++) { + newViewPort = (RList) castParentToViewPort.doCast(newViewPort.getDataAt(ViewPort.PVP_PARENT)); + } + gridState.setViewPort(newViewPort); + + // TODO: device changed? => calcViewportTransform for newViewPort + // TODO: update the clipping region + return RNull.instance; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java new file mode 100644 index 0000000000000000000000000000000000000000..e2b1505d667b9a7ee279f14d5061e4a0e27ed762 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java @@ -0,0 +1,116 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * 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.notEmpty; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; + +import java.util.HashMap; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; + +/** + * External builtin that converts the string representation of a unit, e.g. "cm", to internal + * numerical value. This values are then stored in special attribute "valid.unit". + */ +public abstract class LValidUnit extends RExternalBuiltinNode.Arg1 { + static { + Casts casts = new Casts(LValidUnit.class); + casts.arg(0).mustBe(stringValue(), Message.GENERIC, "'units' must be character").asStringVector().mustBe(notEmpty(), Message.GENERIC, "'units' must be of length > 0"); + } + + public static LValidUnit create() { + return LValidUnitNodeGen.create(); + } + + @Specialization + RIntVector convert(RAbstractStringVector units) { + int[] result = new int[units.getLength()]; + for (int i = 0; i < units.getLength(); i++) { + result[i] = convertSingle(units.getDataAt(i)); + } + return RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR); + } + + private int convertSingle(String name) { + if (name.equals("npc")) { + // seems to be by far the most common unit + return Unit.NPC; + } + return convertSingleSlowPath(name); + } + + @TruffleBoundary + private int convertSingleSlowPath(String name) { + Integer result = NamesHolder.NAMES.get(name); + if (result == null) { + throw error(Message.GENERIC, "invalid unit"); + } + return result; + } + + private static final class NamesHolder { + private static final HashMap<String, Integer> NAMES = new HashMap<>(30); + static { + NAMES.put("npc", Unit.NPC); + NAMES.put("cm", Unit.CM); + NAMES.put("inches", Unit.INCHES); + NAMES.put("lines", Unit.LINES); + NAMES.put("native", Unit.NATIVE); + NAMES.put("null", Unit.NULL); + NAMES.put("snpc", Unit.SNPC); + NAMES.put("mm", Unit.MM); + NAMES.put("points", Unit.POINTS); + NAMES.put("picas", Unit.PICAS); + NAMES.put("bigpts", Unit.BIGPOINTS); + NAMES.put("dida", Unit.DIDA); + NAMES.put("cicero", Unit.CICERO); + NAMES.put("scaledpts", Unit.SCALEDPOINTS); + NAMES.put("strwidth", Unit.STRINGWIDTH); + NAMES.put("strheight", Unit.STRINGHEIGHT); + NAMES.put("strascent", Unit.STRINGASCENT); + NAMES.put("strdescent", Unit.STRINGDESCENT); + + NAMES.put("char", Unit.CHAR); + NAMES.put("grobx", Unit.GROBX); + NAMES.put("groby", Unit.GROBY); + NAMES.put("grobwidth", Unit.GROBWIDTH); + NAMES.put("grobheight", Unit.GROBHEIGHT); + NAMES.put("grobascent", Unit.GROBASCENT); + NAMES.put("grobdescent", Unit.GROBDESCENT); + NAMES.put("mylines", Unit.MYLINES); + NAMES.put("mychar", Unit.MYCHAR); + NAMES.put("mystrwidth", Unit.MYSTRINGWIDTH); + NAMES.put("mystrheight", Unit.MYSTRINGHEIGHT); + // Some pseudonyms + NAMES.put("centimetre", Unit.CM); + NAMES.put("centimetres", Unit.CM); + NAMES.put("centimeter", Unit.CM); + NAMES.put("centimeters", Unit.CM); + NAMES.put("in", Unit.INCHES); + NAMES.put("inch", Unit.INCHES); + NAMES.put("line", Unit.LINES); + NAMES.put("millimetre", Unit.MM); + NAMES.put("millimetres", Unit.MM); + NAMES.put("millimeter", Unit.MM); + NAMES.put("millimeters", Unit.MM); + NAMES.put("point", Unit.POINTS); + NAMES.put("pt", Unit.POINTS); + } + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java new file mode 100644 index 0000000000000000000000000000000000000000..bd5311e91630160f3cbb555a00ac429e672e6f8e --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java @@ -0,0 +1,52 @@ +/* + * 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 com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +public final class Point { + final double x; + final double y; + + public Point(double x, double y) { + this.x = x; + this.y = y; + } + + public static Point fromUnits(RAbstractVector x, RAbstractVector y, int index, UnitConversionContext ctx) { + return new Point(Unit.convertX(x, index, ctx), Unit.convertY(y, index, ctx)); + } + + public Point justify(Size size, double hjust, double vjust) { + return justify(size.getWidth(), size.getHeight(), hjust, vjust); + } + + private Point justify(double width, double height, double hjust, double vjust) { + return new Point(GridUtils.justify(x, width, hjust), GridUtils.justify(y, height, vjust)); + } + + public boolean isFinite() { + return Double.isFinite(x) && Double.isFinite(y); + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java new file mode 100644 index 0000000000000000000000000000000000000000..1dd7e55ce6ac7998b9adf1f3189e91dfdd289a12 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java @@ -0,0 +1,54 @@ +/* + * 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 com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +public final class Size { + private final double width; + private final double height; + + public Size(double width, double height) { + this.width = width; + this.height = height; + } + + public static Size fromUnits(RAbstractVector wVec, RAbstractVector hVec, int index, UnitConversionContext conversionCtx) { + double w = Unit.convertWidth(wVec, index, conversionCtx); + double h = Unit.convertHeight(hVec, index, conversionCtx); + return new Size(w, h); + } + + public double getWidth() { + return width; + } + + public double getHeight() { + return height; + } + + public boolean isFinite() { + return Double.isFinite(width) && Double.isFinite(height); + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java new file mode 100644 index 0000000000000000000000000000000000000000..28ed32b803c8510197c5f581ff4144f0a8b7e6d3 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java @@ -0,0 +1,143 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import static com.oracle.truffle.r.runtime.nmath.MathConstants.M_PI; + +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.Message; + +// transcribed from matrix.c + +/** + * Operations on transformation (3x3) matrices. + */ +final class TransformMatrix { + private TransformMatrix() { + // only static members + } + + static double[][] translation(double tx, double ty) { + double[][] m = identity(); + m[2][0] = tx; + m[2][1] = ty; + return m; + } + + static double[][] multiply(double[][] m1, double[][] m2) { + double[][] m = new double[3][3]; + m[0][0] = m1[0][0] * m2[0][0] + m1[0][1] * m2[1][0] + m1[0][2] * m2[2][0]; + m[0][1] = m1[0][0] * m2[0][1] + m1[0][1] * m2[1][1] + m1[0][2] * m2[2][1]; + m[0][2] = m1[0][0] * m2[0][2] + m1[0][1] * m2[1][2] + m1[0][2] * m2[2][2]; + m[1][0] = m1[1][0] * m2[0][0] + m1[1][1] * m2[1][0] + m1[1][2] * m2[2][0]; + m[1][1] = m1[1][0] * m2[0][1] + m1[1][1] * m2[1][1] + m1[1][2] * m2[2][1]; + m[1][2] = m1[1][0] * m2[0][2] + m1[1][1] * m2[1][2] + m1[1][2] * m2[2][2]; + m[2][0] = m1[2][0] * m2[0][0] + m1[2][1] * m2[1][0] + m1[2][2] * m2[2][0]; + m[2][1] = m1[2][0] * m2[0][1] + m1[2][1] * m2[1][1] + m1[2][2] * m2[2][1]; + m[2][2] = m1[2][0] * m2[0][2] + m1[2][1] * m2[1][2] + m1[2][2] * m2[2][2]; + return m; + } + + static double[][] rotation(double theta) { + double thetarad = theta / 180 * M_PI; + double costheta = Math.cos(thetarad); + double sintheta = Math.sin(thetarad); + double[][] result = identity(); + if (theta == 0) { + return result; + } + result[0][0] = costheta; + result[0][1] = sintheta; + result[1][0] = -sintheta; + result[1][1] = costheta; + return result; + } + + static double[][] identity() { + double[][] result = new double[3][3]; + result[0][0] = 1; + result[1][1] = 1; + result[2][2] = 1; + return result; + } + + private static double[] location(double x, double y) { + return new double[]{x, y, 1}; + } + + private static double[] transLocation(double[] location, double[][] m) { + double[] res = new double[3]; + res[0] = location[0] * m[0][0] + location[1] * m[1][0] + location[2] * m[2][0]; + res[1] = location[0] * m[0][1] + location[1] * m[1][1] + location[2] * m[2][1]; + res[2] = location[0] * m[0][2] + location[1] * m[1][2] + location[2] * m[2][2]; + return res; + } + + static Point transLocation(Point loc, double[][] m) { + double[] newLoc = transLocation(location(loc.x, loc.y), m); + return new Point(locationX(newLoc), locationY(newLoc)); + } + + private static double locationX(double[] loc) { + return loc[0]; + } + + private static double locationY(double[] loc) { + return loc[1]; + } + + /** + * Transforms the internal double matrix to R matrix flat array. + */ + static double[] flatten(double[][] m) { + double[] res = new double[9]; + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + res[i + j * 3] = m[i][j]; + } + } + return res; + } + + /** + * Reverse operation to {@link #flatten(double[][])}. + */ + static double[][] fromFlat(double[] flat) { + double[][] res = new double[3][3]; + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + res[i][j] = flat[i + j * 3]; + } + } + return res; + } + + public static double[][] inversion(double[][] t) { + double det = t[0][0] * (t[2][2] * t[1][1] - t[2][1] * t[1][2]) - + t[1][0] * (t[2][2] * t[0][1] - t[2][1] * t[0][2]) + + t[2][0] * (t[1][2] * t[0][1] - t[1][1] * t[0][2]); + if (det == 0) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "singular transformation matrix"); + } + double[][] invt = new double[3][3]; + invt[0][0] = 1 / det * (t[2][2] * t[1][1] - t[2][1] * t[1][2]); + invt[0][1] = -1 / det * (t[2][2] * t[0][1] - t[2][1] * t[0][2]); + invt[0][2] = 1 / det * (t[1][2] * t[0][1] - t[1][1] * t[0][2]); + invt[1][0] = -1 / det * (t[2][2] * t[1][0] - t[2][0] * t[1][2]); + invt[1][1] = 1 / det * (t[2][2] * t[0][0] - t[2][0] * t[0][2]); + invt[1][2] = -1 / det * (t[1][2] * t[0][0] - t[1][0] * t[0][2]); + invt[2][0] = 1 / det * (t[2][1] * t[1][0] - t[2][0] * t[1][1]); + invt[2][1] = -1 / det * (t[2][1] * t[0][0] - t[2][0] * t[0][1]); + invt[2][2] = 1 / det * (t[1][1] * t[0][0] - t[1][0] * t[0][1]); + return invt; + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..1d6405efaf78e1942d91018099ea19e6c5df9c42 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java @@ -0,0 +1,700 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContainer; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDoubleVector; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asIntVector; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asList; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asListOrNull; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.fmax; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.fmin; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.getDataAtMod; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.getDoubleAt; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.hasRClass; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.sum; +import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_TO_POINTS_FACTOR; + +import java.util.function.BiFunction; + +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.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.RAttributable; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +/** + * Note: internally in FastR Grid everything is in inches. However, some lists that are exposed to + * the R code should contain values in centimeters, we convert such values immediately once they + * enter our system. + */ +public final class Unit { + static final String VALID_UNIT_ATTR = "valid.unit"; + + public static final int NPC = 0; + public static final int CM = 1; + public static final int INCHES = 2; + public static final int LINES = 3; + public static final int NATIVE = 4; + public static final int NULL = 5; /* only used in layout specifications */ + public static final int SNPC = 6; + public static final int MM = 7; + /* + * Some units based on TeX's definition thereof + */ + public static final int POINTS = 8; /* 72.27 pt = 1 in */ + public static final int PICAS = 9; /* 1 pc = 12 pt */ + public static final int BIGPOINTS = 10; /* 72 bp = 1 in */ + public static final int DIDA = 11; /* 1157 dd = 1238 pt */ + public static final int CICERO = 12; /* 1 cc = 12 dd */ + public static final int SCALEDPOINTS = 13; /* 65536 sp = 1pt */ + /* + * Some units which require an object to query for a value. + */ + public static final int STRINGWIDTH = 14; + public static final int STRINGHEIGHT = 15; + public static final int STRINGASCENT = 16; + public static final int STRINGDESCENT = 17; + /* + * LINES now means multiples of the line height. This is multiples of the font size. + */ + public static final int CHAR = 18; + public static final int GROBX = 19; + public static final int GROBY = 20; + public static final int GROBWIDTH = 21; + public static final int GROBHEIGHT = 22; + public static final int GROBASCENT = 23; + public static final int GROBDESCENT = 24; + private static final int LAST_NORMAL_UNIT = GROBDESCENT; + /* + * No longer used + */ + public static final int MYLINES = 103; + public static final int MYCHAR = 104; + public static final int MYSTRINGWIDTH = 105; + public static final int MYSTRINGHEIGHT = 106; + + // null layout arithmetic mode + private static final int L_adding = 1; + private static final int L_subtracting = 2; + private static final int L_summing = 3; + private static final int L_plain = 4; + private static final int L_maximising = 5; + private static final int L_minimising = 6; + private static final int L_multiplying = 7; + + // attributes in the unit object and unit classes + private static final String UNIT_ATTR_DATA = "data"; + private static final String UNIT_ATTR_UNIT_ID = "valid.unit"; + private static final String UNIT_CLASS = "unit"; + private static final String UNIT_ARITHMETIC_CLASS = "unit.arithmetic"; + private static final String UNIT_LIST_CLASS = "unit.list"; + + private static final double CM_IN_INCH = 2.54; + + public static double inchesToCm(double inches) { + return inches * CM_IN_INCH; + } + + public static double cmToInches(double cm) { + return cm / CM_IN_INCH; + } + + public static RAbstractDoubleVector newUnit(double value, int unitId) { + assert unitId > 0 && unitId <= LAST_NORMAL_UNIT; + RDoubleVector result = RDataFactory.createDoubleVector(new double[]{value}, RDataFactory.COMPLETE_VECTOR); + result.setClassAttr(RDataFactory.createStringVectorFromScalar(UNIT_CLASS)); + result.setAttr(UNIT_ATTR_UNIT_ID, unitId); + result.setAttr(UNIT_ATTR_DATA, RNull.instance); + return result; + } + + static double convertFromInches(double value, int unitId, double vpSize, double scalemin, double scalemax, boolean isDimension, DrawingContext drawingCtx) { + switch (unitId) { + case NATIVE: + double addition = isDimension ? 0 : scalemin; + return addition + (value / vpSize) * (scalemax - scalemin); + case NPC: + return value / vpSize; + case CM: + return value * CM_IN_INCH; + case MM: + return value * CM_IN_INCH * 10; + case INCHES: + return value; + case POINTS: + return value * INCH_TO_POINTS_FACTOR; + case PICAS: + return value / 12 * INCH_TO_POINTS_FACTOR; + case BIGPOINTS: + return value * 72; + case DIDA: + return value / 1238 * 1157 * INCH_TO_POINTS_FACTOR; + case CICERO: + return value / 1238 * 1157 * INCH_TO_POINTS_FACTOR / 12; + case SCALEDPOINTS: + return value * 65536 * INCH_TO_POINTS_FACTOR; + case LINES: + return (value * INCH_TO_POINTS_FACTOR) / (drawingCtx.getFontSize() * drawingCtx.getLineHeight()); + // following units are not supported even by original grid + case SNPC: + case MYCHAR: + case MYLINES: + case STRINGWIDTH: + case MYSTRINGWIDTH: + case STRINGHEIGHT: + case MYSTRINGHEIGHT: + case GROBX: + case GROBY: + case GROBWIDTH: + case GROBHEIGHT: + case NULL: + default: + throw RInternalError.unimplemented("unit type " + unitId + " in convertFromInches"); + } + } + + private static double convertToInches(double value, int index, int unitId, RList data, UnitConversionContext ctx, AxisOrDimension axisOrDim) { + // Note: grob units are converted in a dedicated node + double vpSize = ctx.getViewPortSize(axisOrDim); + String str; + String[] lines; + double result = 0; + switch (unitId) { + case INCHES: + return value; + case NATIVE: + double tmp = axisOrDim.isDimension() ? value : (value - ctx.getScaleMin(axisOrDim)); + return (tmp / (ctx.getScaleMax(axisOrDim) - ctx.getScaleMin(axisOrDim))) * vpSize; + case NPC: + return value * vpSize; + case POINTS: + return value / INCH_TO_POINTS_FACTOR; + case CM: + return value / CM_IN_INCH; + case MM: + return value / (CM_IN_INCH * 10); + case PICAS: + return (value * 12) / INCH_TO_POINTS_FACTOR; + case BIGPOINTS: + return value / 72; + case DIDA: + return value / 1157 * 1238 / INCH_TO_POINTS_FACTOR; + case CICERO: + return value * 12 / 1157 * 1238 / INCH_TO_POINTS_FACTOR; + case SCALEDPOINTS: + return value / 65536 / INCH_TO_POINTS_FACTOR; + case CHAR: + case MYCHAR: + return (value * ctx.gpar.getDrawingContext(index).getFontSize()) / INCH_TO_POINTS_FACTOR; + case LINES: + case MYLINES: + return (value * ctx.gpar.getDrawingContext(index).getFontSize() * ctx.gpar.getDrawingContext(index).getLineHeight()) / INCH_TO_POINTS_FACTOR; + 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; + case STRINGHEIGHT: + case MYSTRINGHEIGHT: + str = RRuntime.asString(data.getDataAt(0)); + lines = str.split("\n"); + for (String line : lines) { + result += ctx.device.getStringHeight(ctx.gpar.getDrawingContext(index), line); + } + return value * result; + case NULL: + return evaluateNullUnit(value, vpSize, ctx.nullLayoutMode, ctx.nullArithmeticMode); + default: + throw RInternalError.unimplemented("unit type " + unitId + " in convertToInches"); + } + } + + private static double evaluateNullUnit(double value, double vpSize, int nullLMode, int nullAMode) { + if (nullLMode > 0) { + return value; + } + switch (nullAMode) { + case L_plain: + case L_adding: + case L_subtracting: + case L_summing: + case L_multiplying: + case L_maximising: + return 0; + case L_minimising: + return vpSize; // Note: GnuR has vpSize in "cm", so this will be in "cm" + // too, does it matter? + } + return value; + } + + static boolean isListUnit(Object unit) { + return unit instanceof RList && hasRClass((RAttributable) unit, UNIT_LIST_CLASS); + } + + static boolean isArithmeticUnit(Object unit) { + return unit instanceof RList && hasRClass((RAttributable) unit, UNIT_ARITHMETIC_CLASS); + } + + private static boolean isGrobUnit(int unitId) { + return unitId >= GROBX && unitId <= GROBDESCENT; + } + + private static final class PureNullUniValueVisitor extends UnitVisitor<Double, Integer> { + private static final PureNullUniValueVisitor INSTANCE = new PureNullUniValueVisitor(); + + @Override + protected Double visitListUnit(RList unit, Integer index) { + return visit(asAbstractContainer(unit.getDataAt(index % unit.getLength())), 0); + } + + @Override + protected Double visitArithmeticUnit(ArithmeticUnit expr, Integer index) { + switch (expr.op) { + case "+": + return visit(expr.arg1, index) + visit(expr.arg2, index); + case "-": + return visit(expr.arg1, index) - visit(expr.arg2, index); + case "*": + return asDouble(expr.arg1) * visit(expr.arg2, index); + case "min": + case "max": + case "sum": + double[] values = new double[expr.arg1.getLength()]; + for (int i = 0; i < values.length; i++) { + values[i] = visit(expr.arg1, i); + } + switch (expr.op) { + case "min": + return fmin(Double.MAX_VALUE, values); + case "max": + return fmax(Double.MIN_VALUE, values); + case "sum": + return sum(values); + } + } + throw RInternalError.shouldNotReachHere("unexpected arithmetic unit operation"); + } + + @Override + protected Double visitSimpleUnit(RAbstractVector unit, Integer index) { + return GridUtils.getDoubleAt(unit, index); + } + } + + static double pureNullUnitValue(RAbstractContainer unit, int index) { + return PureNullUniValueVisitor.INSTANCE.visit(unit, index); + } + + public static boolean isSimpleUnit(RAbstractContainer unit) { + RStringVector classAttr = unit.getClassAttr(); + if (classAttr == null || classAttr.getLength() == 0) { + return true; + } + for (int i = 0; i < classAttr.getLength(); i++) { + String x = classAttr.getDataAt(i); + if (Unit.UNIT_ARITHMETIC_CLASS.equals(x) || Unit.UNIT_LIST_CLASS.equals(x)) { + return false; + } + } + return true; + } + + private static final class ArithmeticUnit { + public final String op; + public final RAbstractContainer arg1; + public final RAbstractContainer arg2; + + ArithmeticUnit(String op, RAbstractContainer arg1, RAbstractContainer arg2) { + this.op = op; + this.arg1 = arg1; + this.arg2 = arg2; + } + + static ArithmeticUnit asArithmeticUnit(RList unit) { + if (unit.getLength() <= 1) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Invalid arithmetic unit (length <= 1)."); + } + // Note: the operator is usually of type character, however in the R code, grid compares + // it to symbols, e.g. `x`. Our implementation here should work with symbols too thanks + // to the asStringVector() conversion. + String op = RRuntime.asString(unit.getDataAt(0)); + RAbstractContainer arg1 = asAbstractContainer(unit.getDataAt(1)); + if (op.equals("+") || op.equals("-") || op.equals("*")) { + if (unit.getLength() != 3) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Invalid arithmetic unit with binary operator and missing operand."); + } + return new ArithmeticUnit(op, arg1, asAbstractContainer(unit.getDataAt(2))); + } + if (op.equals("max") || op.equals("min") || op.equals("sum")) { + return new ArithmeticUnit(op, arg1, null); + } + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected unit operator " + op); + } + + public boolean isBinary() { + return arg2 != null; + } + } + + private abstract static class UnitVisitor<T, R> { + public T visit(RAbstractContainer unit, R arg) { + RStringVector clazz = unit.getClassAttr(); + if (clazz == null || clazz.getLength() == 0) { + return visitSimpleUnit((RAbstractVector) unit, arg); + } + for (int i = 0; i < clazz.getLength(); i++) { + String className = clazz.getDataAt(i); + if (UNIT_ARITHMETIC_CLASS.equals(className)) { + return visitArithmeticUnit(ArithmeticUnit.asArithmeticUnit(asList(unit)), arg); + } + if (UNIT_LIST_CLASS.equals(className)) { + return visitListUnit(asList(unit), arg); + } + } + return visitSimpleUnit((RAbstractVector) unit, arg); + } + + public T visit(RAbstractContainer unit) { + return visit(unit, null); + } + + protected T visitListUnit(RList unit) { + throw RInternalError.shouldNotReachHere(); + } + + protected T visitArithmeticUnit(ArithmeticUnit unit) { + throw RInternalError.shouldNotReachHere(); + } + + protected T visitSimpleUnit(RAbstractVector unit) { + throw RInternalError.shouldNotReachHere(); + } + + protected T visitListUnit(RList unit, R arg) { + return visitListUnit(unit); + } + + protected T visitArithmeticUnit(ArithmeticUnit unit, R arg) { + return visitArithmeticUnit(unit); + } + + protected T visitSimpleUnit(RAbstractVector unit, R arg) { + return visitSimpleUnit(unit); + } + } + + private static final class UnitLengthVisitor extends UnitVisitor<Integer, Object> { + private static final UnitLengthVisitor INSTANCE = new UnitLengthVisitor(); + + @Override + protected Integer visitListUnit(RList unit) { + return unit.getLength(); + } + + @Override + protected Integer visitArithmeticUnit(ArithmeticUnit unit) { + // length of aggregate functions, max, min, etc. is 1 + return unit.isBinary() ? Math.max(visit(unit.arg1), visit(unit.arg2)) : 1; + } + + @Override + protected Integer visitSimpleUnit(RAbstractVector unit) { + return unit.getLength(); + } + } + + /** + * Arithmetic unit objects can represent 'vectorized' expressions, e.g. + * {@code 3*c(unit(1,'cm'), unit(2,'mm'))}, in such case the 'length' is not simply the length + * of the underlying vector/list. + */ + public static int getLength(RAbstractContainer unit) { + return UnitLengthVisitor.INSTANCE.visit(unit); + } + + /** + * Returns {@code true} if the given unit object represents a unit without actual unit type, + * i.e. the unit type is {@link #NULL}. Such units are used internally for layouting, and the + * interpretation is to take-up all the left space (evenly if there are more such units). + */ + public static boolean isRelativeUnit(GridContext ctx, Object unit, int index) { + GridState gridState = ctx.getGridState(); + return gridState.runWithoutRecording(() -> { + Object result = ctx.evalInternalRFunction("isPureNullUnit", unit, index + 1); + return RRuntime.fromLogical(RRuntime.asLogicalObject(result)); + }); + } + + /** + * Used to discriminate between x axis, y axis, width, and height when doing unit conversions. + * The order should be the same as used in e.g. {@code L_convert}, which is 0 means x, 1 means + * y, 2 means width, 3 means height. + */ + public enum AxisOrDimension { + X, + Y, + WIDTH, + HEIGHT; + + private static final AxisOrDimension[] enumValues = values(); + + static AxisOrDimension fromInt(int value) { + assert value >= 0 && value < 4; + return enumValues[value]; + } + + public boolean isHorizontal() { + return this == X || this == WIDTH; + } + + public boolean isDimension() { + return this == WIDTH || this == HEIGHT; + } + } + + /** + * Wraps the data necessary for converting a unit to another unit. Note: {@code nullLMode} and + * {@code nullAMode} is only used for converting 'NULL' units and is only explicitly set when + * calculating layout. When e.g. drawing or calculating bounds, both should have default zero + * value. + */ + public static final class UnitConversionContext { + public final Size viewPortSize; + public final ViewPortContext viewPortContext; + public final GPar gpar; + public final GridDevice device; + public final int nullLayoutMode; + public final int nullArithmeticMode; + + public UnitConversionContext(Size viewPortSize, ViewPortContext viewPortContext, GridDevice device, GPar gpar) { + this(viewPortSize, viewPortContext, device, gpar, 0, 0); + } + + public UnitConversionContext(Size viewPortSize, ViewPortContext viewPortContext, GridDevice device, GPar gpar, int nullLMode, int nullAMode) { + this.viewPortSize = viewPortSize; + this.viewPortContext = viewPortContext; + this.device = device; + this.gpar = gpar; + this.nullLayoutMode = nullLMode; + this.nullArithmeticMode = nullAMode; + } + + public double getViewPortSize(AxisOrDimension forAxisOrDim) { + return forAxisOrDim.isHorizontal() ? viewPortSize.getWidth() : viewPortSize.getHeight(); + } + + public double getScaleMin(AxisOrDimension forAxisOrDim) { + return forAxisOrDim.isHorizontal() ? viewPortContext.xscalemin : viewPortContext.yscalemin; + } + + public double getScaleMax(AxisOrDimension forAxisOrDim) { + return forAxisOrDim.isHorizontal() ? viewPortContext.xscalemax : viewPortContext.yscalemax; + } + } + + private static final class UnitConversionArgs { + public final UnitConversionContext ctx; + public final AxisOrDimension axisOrDim; + public final int index; + + UnitConversionArgs(int index, UnitConversionContext ctx, AxisOrDimension axisOrDim) { + this.ctx = ctx; + this.axisOrDim = axisOrDim; + this.index = index; + } + } + + private static final class UnitConvertVisitor extends UnitVisitor<Double, UnitConversionArgs> { + private static final UnitConvertVisitor INSTANCE = new UnitConvertVisitor(); + + @Override + protected Double visitSimpleUnit(RAbstractVector value, UnitConversionArgs args) { + int unitId = getDataAtMod(asIntVector(value.getAttr(UNIT_ATTR_UNIT_ID)), args.index); + double scalarValue = getDoubleAt(value, args.index % value.getLength()); + if (isGrobUnit(unitId)) { + RList grobList = asList(value.getAttr(UNIT_ATTR_DATA)); + return grobUnitToInches(scalarValue, unitId, grobList.getDataAt(args.index % grobList.getLength()), args.ctx); + } + return convertToInches(scalarValue, args.index, unitId, asListOrNull(value.getAttr(UNIT_ATTR_DATA)), args.ctx, args.axisOrDim); + } + + @Override + protected Double visitListUnit(RList unit, UnitConversionArgs args) { + return visit(asAbstractContainer(unit.getDataAt(args.index % unit.getLength())), new UnitConversionArgs(0, args.ctx, args.axisOrDim)); + } + + @Override + protected Double visitArithmeticUnit(ArithmeticUnit expr, UnitConversionArgs args) { + BiFunction<RAbstractContainer, Integer, Double> recursive = (x, newNullAMode) -> visit(x, + new UnitConversionArgs(args.index, getNewCtx(args.ctx, args.axisOrDim, newNullAMode), args.axisOrDim)); + switch (expr.op) { + case "+": + return recursive.apply(expr.arg1, L_adding) + recursive.apply(expr.arg2, L_adding); + case "-": + return recursive.apply(expr.arg1, L_subtracting) - recursive.apply(expr.arg2, L_subtracting); + case "*": + RAbstractDoubleVector left = asDoubleVector(expr.arg1); + return left.getDataAt(args.index % left.getLength()) * recursive.apply(expr.arg2, L_multiplying); + default: + break; + } + + // must be aggregate operation + UnitConversionContext newCtx = getNewCtx(args.ctx, args.axisOrDim, getNullAMode(expr.op)); + int len = getLength(expr.arg1); + double[] values = new double[len]; + for (int i = 0; i < len; i++) { + values[i] = visit(expr.arg1, new UnitConversionArgs(i, newCtx, args.axisOrDim)); + } + + switch (expr.op) { + case "min": + return GridUtils.fmin(Double.MAX_VALUE, values); + case "max": + return GridUtils.fmax(Double.MIN_VALUE, values); + case "sum": + return GridUtils.sum(values); + default: + throw RInternalError.shouldNotReachHere("The operation should have been validated in asArithmeticUnit method."); + } + } + + // Note the catch: newNullAMode is applied only if the axisOrDim is dimension + private static UnitConversionContext getNewCtx(UnitConversionContext ctx, AxisOrDimension axisOrDim, int newNullAMode) { + return new UnitConversionContext(ctx.viewPortSize, ctx.viewPortContext, ctx.device, ctx.gpar, ctx.nullLayoutMode, + axisOrDim.isDimension() ? newNullAMode : ctx.nullArithmeticMode); + } + + private static int getNullAMode(String op) { + switch (op) { + case "min": + return L_minimising; + case "max": + return L_maximising; + case "sum": + return L_summing; + } + return L_plain; + } + } + + public static double convert(RAbstractContainer unit, int index, UnitConversionContext ctx, AxisOrDimension axisOrDim) { + return UnitConvertVisitor.INSTANCE.visit(unit, new UnitConversionArgs(index, ctx, axisOrDim)); + } + + public static double convertX(RAbstractContainer unit, int index, UnitConversionContext ctx) { + return convert(unit, index, ctx, AxisOrDimension.X); + } + + public static double convertY(RAbstractContainer unit, int index, UnitConversionContext ctx) { + return convert(unit, index, ctx, AxisOrDimension.Y); + } + + public static double convertWidth(RAbstractContainer unit, int index, UnitConversionContext ctx) { + return convert(unit, index, ctx, AxisOrDimension.WIDTH); + } + + public static double convertHeight(RAbstractContainer unit, int index, UnitConversionContext ctx) { + return convert(unit, index, ctx, AxisOrDimension.HEIGHT); + } + + public static double convertDimension(RAbstractContainer unit, int index, UnitConversionContext ctx, boolean isWidth) { + return convert(unit, index, ctx, isWidth ? AxisOrDimension.WIDTH : AxisOrDimension.HEIGHT); + } + + private static double grobUnitToInches(double value, int unitId, Object grob, UnitConversionContext conversionCtx) { + return GridContext.getContext().getGridState().runWithoutRecording(() -> grobUnitToInchesImpl(value, unitId, grob, conversionCtx)); + } + + private static double grobUnitToInchesImpl(double value, int unitId, Object grob, UnitConversionContext conversionCtx) { + GridContext ctx = GridContext.getContext(); + RList currentVP = ctx.getGridState().getViewPort(); + // This may update the VP if the device size has changed + ViewPortTransform.get(currentVP, conversionCtx.device); + + RList savedGPar = ctx.getGridState().getGpar(); + Object savedGrob = ctx.getGridState().getCurrentGrob(); + + Object updatedGrob = ctx.evalInternalRFunction("grobConversionPreDraw", grob); + + /* + * The call to preDraw may have pushed viewports and/or enforced gpar settings, SO we need + * to re-establish the current viewport and gpar settings before evaluating the width unit. + */ + currentVP = ctx.getGridState().getViewPort(); + RList currentGP = ctx.getGridState().getGpar(); + ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, conversionCtx.device); + ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP); + + // getUnitXY returns a list with either one or two items + RList unitxy = (RList) ctx.evalInternalRFunction("grobConversionGetUnitXY", updatedGrob, unitId, value); + double result; + switch (unitId) { + case GROBX: + case GROBY: + if (unitId == GROBY && isRelativeUnit(ctx, unitxy.getDataAt(1), 0)) { + double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(1), 0); + result = evaluateNullUnit(nullUnitValue, vpTransform.size.getHeight(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode); + } else if (isRelativeUnit(ctx, unitxy.getDataAt(0), 0)) { + double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(0), 0); + result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode); + } else { + double[][] inversed = TransformMatrix.inversion(vpTransform.transform); + Point loc = Point.fromUnits((RAbstractVector) unitxy.getDataAt(0), (RAbstractVector) unitxy.getDataAt(1), 0, conversionCtx); + Point transLoc = TransformMatrix.transLocation(loc, vpTransform.transform); + Point p = TransformMatrix.transLocation(transLoc, inversed); + result = unitId == GROBX ? p.x : p.y; + } + break; + default: + // should still be GROB_SOMETHING unit: width, height, ascent, descent + if (isRelativeUnit(ctx, unitxy.getDataAt(0), 0)) { + // Note: GnuR uses equivalent of vpTransform.size.getWidth() even for + // GROBHEIGHT, bug? + double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(0), 0); + result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode); + } else { + UnitConversionContext newConversionCtx = new UnitConversionContext(vpTransform.size, vpContext, conversionCtx.device, GPar.create(currentGP)); + if (unitId == GROBWIDTH) { + result = convertWidth((RAbstractContainer) unitxy.getDataAt(0), 0, newConversionCtx); + } else { + // Note: GnuR uses height transform for both grobascent, grobdescent and + // for height + result = convertHeight((RAbstractContainer) unitxy.getDataAt(0), 0, newConversionCtx); + } + } + result *= value; + break; + } + + ctx.evalInternalRFunction("grobConversionPostDraw", updatedGrob); + ctx.getGridState().setGpar(savedGPar); + ctx.getGridState().setCurrentGrob(savedGrob); + return result; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java new file mode 100644 index 0000000000000000000000000000000000000000..6bd2592e1610cafb8fd09614d33457f6387881da --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java @@ -0,0 +1,166 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asList; +import static com.oracle.truffle.r.library.fastrGrid.Unit.inchesToCm; + +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; +import com.oracle.truffle.r.nodes.function.call.RExplicitCallNode; +import com.oracle.truffle.r.runtime.RRuntime; +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.model.RAbstractDoubleVector; + +/** + * There is a notion of a view point, which is an ordinary list that user creates to define a view + * port. One such list is pushed using {@code pushViewpoint} it is transformed to a 'pushed + * viewpoint', which is a copy of the original view point and it has some additional attributes. + */ +final class ViewPort { + /* + * Structure of a viewport + */ + public static final int VP_X = 0; + public static final int VP_Y = 1; + public static final int VP_WIDTH = 2; + public static final int VP_HEIGHT = 3; + public static final int VP_JUST = 4; + public static final int VP_GP = 5; + public static final int VP_CLIP = 6; + public static final int VP_XSCALE = 7; + public static final int VP_YSCALE = 8; + public static final int VP_ANGLE = 9; + public static final int VP_LAYOUT = 10; + public static final int VP_LPOSROW = 11; + public static final int VP_LPOSCOL = 12; + public static final int VP_VALIDJUST = 13; + public static final int VP_VALIDLPOSROW = 14; + public static final int VP_VALIDLPOSCOL = 15; + public static final int VP_NAME = 16; + /* + * Additional structure of a pushedvp + */ + public static final int PVP_PARENTGPAR = 17; + public static final int PVP_GPAR = 18; + public static final int PVP_TRANS = 19; + public static final int PVP_WIDTHS = 20; + public static final int PVP_HEIGHTS = 21; + public static final int PVP_WIDTHCM = 22; + public static final int PVP_HEIGHTCM = 23; + public static final int PVP_ROTATION = 24; + public static final int PVP_CLIPRECT = 25; + public static final int PVP_PARENT = 26; + public static final int PVP_CHILDREN = 27; + public static final int PVP_DEVWIDTHCM = 28; + public static final int PVP_DEVHEIGHTCM = 29; + /* + * Structure of a layout + */ + private static final int LAYOUT_NROW = 0; + private static final int LAYOUT_NCOL = 1; + public static final int LAYOUT_WIDTHS = 2; + public static final int LAYOUT_HEIGHTS = 3; + public static final int LAYOUT_RESPECT = 4; + public static final int LAYOUT_VRESPECT = 5; + public static final int LAYOUT_MRESPECT = 6; + public static final int LAYOUT_JUST = 7; + private static final int LAYOUT_VJUST = 8; + + /** + * Updates the device size in the viewport and returns {@code true} if the size has changed. + */ + public static boolean updateDeviceSizeInVP(RList viewPort, GridDevice device) { + double devWidthCm = inchesToCm(device.getWidth()); + boolean result = false; + if (Math.abs(devWidthCm - asDouble(viewPort.getDataAt(PVP_DEVWIDTHCM))) >= 1e-6) { + viewPort.setDataAt(viewPort.getInternalStore(), PVP_DEVWIDTHCM, devWidthCm); + result = true; + } + double devHeightCm = inchesToCm(device.getHeight()); + if (Math.abs(devHeightCm - asDouble(viewPort.getDataAt(PVP_DEVHEIGHTCM))) >= 1e-6) { + viewPort.setDataAt(viewPort.getInternalStore(), PVP_DEVHEIGHTCM, devHeightCm); + } + return result; + } + + /** + * Represents the integer values extracted from {@link #LAYOUT_NCOL} and {@link #LAYOUT_NROW}. + * In the R world, RNulls are valid values for those, we convert them to -1 to keep type safety. + * The values should be interpreted as 0-based indexes. + */ + public static final class LayoutPos { + public final int colMin; + public final int colMax; + public final int rowMin; + public final int rowMax; + public final LayoutSize layoutSize; + + LayoutPos(int colMin, int colMax, int rowMin, int rowMax, LayoutSize layoutSize) { + this.colMin = colMin; + this.colMax = colMax; + this.rowMin = rowMin; + this.rowMax = rowMax; + this.layoutSize = layoutSize; + } + } + + /** + * The values should be interpreted as 0-based indexes. + */ + public static final class LayoutSize { + public final int ncol; + public final int nrow; + public final double hjust; + public final double vjust; + + private LayoutSize(int nrow, int ncol, double hjust, double vjust) { + this.ncol = ncol; + this.nrow = nrow; + this.hjust = hjust; + this.vjust = vjust; + } + + public static LayoutSize fromViewPort(RList vp) { + RList layout = asList(vp.getDataAt(ViewPort.VP_LAYOUT)); + int ncol = RRuntime.asInteger(layout.getDataAt(ViewPort.LAYOUT_NCOL)); + int nrow = RRuntime.asInteger(layout.getDataAt(ViewPort.LAYOUT_NROW)); + RAbstractDoubleVector just = (RAbstractDoubleVector) layout.getDataAt(ViewPort.LAYOUT_VJUST); + return new LayoutSize(nrow, ncol, just.getDataAt(0), just.getDataAt(1)); + } + } + + public static final class InitViewPortNode extends Node { + @Child private ReadVariableNode readGridTopLevel = ReadVariableNode.create("grid.top.level.vp"); + @Child private RExplicitCallNode callNode = RExplicitCallNode.create(); + + public RList execute(VirtualFrame frame) { + RFunction gridTopLevel = (RFunction) readGridTopLevel.execute(frame); + RList topVP = (RList) callNode.execute(frame, gridTopLevel, RArgsValuesAndNames.EMPTY); + topVP.makeSharedPermanent(); + + GridDevice device = GridContext.getContext().getCurrentDevice(); + // TODO: properly set the scale according to the current device + Object[] data = topVP.getDataWithoutCopying(); + data[ViewPort.VP_XSCALE] = RDataFactory.createDoubleVector(new double[]{0, device.getWidth()}, RDataFactory.COMPLETE_VECTOR); + data[ViewPort.VP_YSCALE] = RDataFactory.createDoubleVector(new double[]{0, device.getHeight()}, RDataFactory.COMPLETE_VECTOR); + data[ViewPort.PVP_GPAR] = GridContext.getContext().getGridState().getGpar(); + return DoSetViewPort.doSetViewPort(topVP, false, true); + } + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java new file mode 100644 index 0000000000000000000000000000000000000000..0eb93b84f92ae34ba54ddf944a0e867bb9bfde62 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java @@ -0,0 +1,55 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDoubleVector; + +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; + +public final class ViewPortContext { + public double xscalemin; + public double yscalemin; + public double xscalemax; + public double yscalemax; + + private ViewPortContext() { + } + + public static ViewPortContext createDefault() { + ViewPortContext result = new ViewPortContext(); + result.xscalemin = 0; + result.yscalemin = 0; + result.xscalemax = 1; + result.yscalemax = 1; + return result; + } + + public static ViewPortContext fromViewPort(RList viewPort) { + ViewPortContext result = new ViewPortContext(); + RAbstractDoubleVector x = asDoubleVector(viewPort.getDataAt(ViewPort.VP_XSCALE)); + if (x.getLength() != 2) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "view-port xscale must be vector of size 2"); + } + result.xscalemin = x.getDataAt(0); + result.xscalemax = x.getDataAt(1); + RAbstractDoubleVector y = asDoubleVector(viewPort.getDataAt(ViewPort.VP_YSCALE)); + if (y.getLength() != 2) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "view-port yscale must be vector of size 2"); + } + result.yscalemin = y.getDataAt(0); + result.yscalemax = y.getDataAt(1); + return result; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java new file mode 100644 index 0000000000000000000000000000000000000000..cd45334acef3858aa9d0f40f7eb58faf3b9e179f --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java @@ -0,0 +1,49 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContainer; +import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDoubleVector; + +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; + +/** + * The vectors in this class represent a unit objects, therefore we cannot just have a double value + * for them. However, the unit object should contain only single value. + */ +public final class ViewPortLocation { + public RAbstractContainer x; + public RAbstractContainer y; + public RAbstractContainer width; + public RAbstractContainer height; + public double hjust; + public double vjust; + + public static ViewPortLocation fromViewPort(RList viewPort) { + ViewPortLocation r = new ViewPortLocation(); + r.x = asAbstractContainer(viewPort.getDataAt(ViewPort.VP_X)); + r.y = asAbstractContainer(viewPort.getDataAt(ViewPort.VP_Y)); + r.width = asAbstractContainer(viewPort.getDataAt(ViewPort.VP_WIDTH)); + r.height = asAbstractContainer(viewPort.getDataAt(ViewPort.VP_HEIGHT)); + RAbstractDoubleVector just = asDoubleVector(viewPort.getDataAt(ViewPort.VP_VALIDJUST)); + if (just.getLength() != 2) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected size of layout justification vector."); + } + r.hjust = just.getDataAt(0); + r.vjust = just.getDataAt(1); + return r; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java new file mode 100644 index 0000000000000000000000000000000000000000..179ec60d185947d6dbffb883dca04063d8b9b92f --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java @@ -0,0 +1,48 @@ +/* + * 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) 2001-3 Paul Murrell + * Copyright (c) 1998-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid; + +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; + +/** + * Holds the data of a viewport needed to perform transformations. + */ +public final class ViewPortTransform { + /** + * Angle in radians. + */ + public final double rotationAngle; + public final double[][] transform; + public final Size size; + + private ViewPortTransform(double width, double height, double rotationAngle, double[][] transform) { + this.size = new Size(width, height); + this.rotationAngle = rotationAngle; + this.transform = transform; + } + + public static ViewPortTransform get(RList viewPort, GridDevice device) { + if (ViewPort.updateDeviceSizeInVP(viewPort, device)) { + // Note: GnuR sets incremental parameter to true, but don't we need to recalculate + // the parent(s) as well? + DoSetViewPort.calcViewportTransform(viewPort, viewPort.getDataAt(ViewPort.PVP_PARENT), true, device, GridState.getInitialGPar(device)); + } + double width = Unit.cmToInches(GridUtils.asDouble(viewPort.getDataAt(ViewPort.PVP_WIDTHCM))); + double height = Unit.cmToInches(GridUtils.asDouble(viewPort.getDataAt(ViewPort.PVP_HEIGHTCM))); + double rotationAngle = GridUtils.asDouble(viewPort.getDataAt(ViewPort.VP_ANGLE)); + RAbstractDoubleVector trans = GridUtils.asDoubleVector(viewPort.getDataAt(ViewPort.PVP_TRANS)); + double[][] transform = TransformMatrix.fromFlat(trans.materialize().getDataWithoutCopying()); + return new ViewPortTransform(width, height, rotationAngle, transform); + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/WindowDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/WindowDevice.java new file mode 100644 index 0000000000000000000000000000000000000000..6ed69613fc9f40a42972fa6609e150c5a51938b9 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/WindowDevice.java @@ -0,0 +1,72 @@ +/* + * 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 com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedJFrameDevice; +import com.oracle.truffle.r.library.fastrGrid.device.awt.JFrameDevice; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.context.RContext; + +/** + * Contains code specific to FastR device that shows the graphical output interactively in a window. + */ +public final class WindowDevice { + private WindowDevice() { + // only static members + } + + public static GridDevice createWindowDevice() { + return createWindowDevice(GridDevice.DEFAULT_WIDTH, GridDevice.DEFAULT_HEIGHT); + } + + public static GridDevice createWindowDevice(int width, int height) { + JFrameDevice frameDevice = JFrameDevice.create(width, height); + if (RContext.getInstance().hasExecutor()) { + frameDevice.setResizeListener(WindowDevice::redrawAll); + } else { + noSchedulingSupportWarning(); + } + return new BufferedJFrameDevice(frameDevice); + } + + public static RError awtNotSupported() { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "AWT based grid devices are not supported."); + } + + private static void redrawAll() { + RContext ctx = RContext.getInstance(); + if (ctx.hasExecutor()) { + // to be robust we re-check the executor availability + ctx.schedule(() -> { + GridContext.getContext().evalInternalRFunction("redrawAll"); + }); + } + } + + private static void noSchedulingSupportWarning() { + // Note: the PolyglotEngine was not built with an Executor + RError.warning(RError.NO_CALLER, Message.GENERIC, "Grid cannot resize the drawings. If you resize the window, the content will be lost."); + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java new file mode 100644 index 0000000000000000000000000000000000000000..dcfb747b4f7be4595bc795e2b31b08c1fd74d353 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java @@ -0,0 +1,166 @@ +/* + * 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.device; + +/** + * Defines parameters for drawing, like color, line style etc. The implementations must be + * immutable. + */ +public interface DrawingContext { + double INCH_TO_POINTS_FACTOR = 72.27; + + String FONT_FAMILY_MONO = "mono"; + String FONT_FAMILY_SANS = "sans"; + String FONT_FAMILY_SERIF = "serif"; + + byte[] GRID_LINE_BLANK = null; + byte[] GRID_LINE_SOLID = new byte[0]; + + enum GridFontStyle { + PLAIN, + BOLD, + ITALIC, + BOLDITALIC, + /** + * Supposed to be symbol font in Adobe symbol encoding. + */ + SYMBOL; + + /** + * Return enum's value corresponding to R's value. + */ + public static GridFontStyle fromInt(int num) { + assert num > 0 && num <= SYMBOL.ordinal() + 1; + return values()[num - 1]; + } + + public boolean isBold() { + return this == BOLD || this == BOLDITALIC; + } + + public boolean isItalic() { + return this == ITALIC || this == BOLDITALIC; + } + } + + enum GridLineJoin { + ROUND, + MITRE, + BEVEL; + + public static final int LAST_VALUE = BEVEL.ordinal(); + + /** + * Return enum's value corresponding to R's value. + */ + public static GridLineJoin fromInt(int num) { + return values()[num]; + } + } + + enum GridLineEnd { + ROUND, + BUTT, + SQUARE; + + public static final int LAST_VALUE = SQUARE.ordinal(); + + /** + * Return enum's value corresponding to R's value. + */ + public static GridLineEnd fromInt(int num) { + return values()[num]; + } + } + + /** + * Returns either one of the constants {@link #GRID_LINE_BLANK} or {@link #GRID_LINE_SOLID} or + * an array with a pattern consisting of lengths. Lengths at odd positions are dashes and + * lengths at the even positions are spaces between them, the pattern should be interpreted as + * cyclic. Example: '3,2,10,1' means 3 units of line, 2 units of space, 10 units of line, 1 unit + * of space and repeat. The unit here can be device dependent, but should be something "small", + * like a pixel. + */ + byte[] getLineType(); + + /** + * Line width in multiplies of what is considered the basic "thin" line for given device. + */ + double getLineWidth(); + + GridLineJoin getLineJoin(); + + GridLineEnd getLineEnd(); + + /** + * The mitre limit, larger than 1, default is 10. The unit should be interpreted the way as in + * {@link #getLineType()}. + */ + double getLineMitre(); + + /** + * Drawing color of shape borders, lines and text. + */ + GridColor getColor(); + + /** + * Gets the font size in points. + * + * @see #INCH_TO_POINTS_FACTOR + */ + double getFontSize(); + + GridFontStyle getFontStyle(); + + /** + * Gets the font family name. The standard values that any device must implement are "serif", + * "sans" and "mono". On top of that the device can recognize name of any font that it can + * support. + */ + String getFontFamily(); + + /** + * Gets the height of a text line in multiplies of the base line height. This is typically not a + * concern of devices, since they always receive single line strings for drawing. + */ + double getLineHeight(); + + /** + * The fill color of shapes. + */ + GridColor getFillColor(); + + static boolean areSame(DrawingContext ctx1, DrawingContext ctx2) { + return ctx1 == ctx2 || (ctx1.getColor().equals(ctx2.getColor()) && + ctx1.getLineEnd() == ctx2.getLineEnd() && + ctx1.getLineJoin() == ctx2.getLineJoin() && + ctx1.getLineType() == ctx2.getLineType() && + ctx1.getLineHeight() == ctx2.getLineHeight() && + ctx1.getFontStyle() == ctx2.getFontStyle() && + ctx1.getFontSize() == ctx2.getFontSize() && + ctx1.getFontFamily().equals(ctx2.getFontFamily()) && + ctx1.getLineWidth() == ctx2.getLineWidth() && + ctx1.getLineMitre() == ctx2.getLineMitre() && + ctx1.getFillColor().equals(ctx2.getFillColor())); + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContextDefaults.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContextDefaults.java new file mode 100644 index 0000000000000000000000000000000000000000..7aa6f3f9b46e5cd2e65363a4fec109a42f39f758 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContextDefaults.java @@ -0,0 +1,32 @@ +/* + * 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.device; + +/** + * Allows the device to communicate the default values for its initial {@link DrawingContext}. The + * format of the values is the same as accepted by the {@code gpar()} function in R. + */ +public final class DrawingContextDefaults { + public String fillColor = "transparent"; + public String color = "black"; +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..28abf944f1eae6088260398ccf7c9103c7118733 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.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.library.fastrGrid.device; + +/** + * Simple color representation, so that the device interface does not have to depend on a specific + * GUI framework. + */ +public final class GridColor { + public static final int OPAQUE_ALPHA = 0xff; + private static final int TRANSPARENT_ALPHA = 0; + public static final GridColor TRANSPARENT = new GridColor(0, 0, 0, TRANSPARENT_ALPHA); + + private final int value; + + public GridColor(int red, int green, int blue, int alpha) { + value = ((alpha & 0xFF) << 24) | + ((red & 0xFF) << 16) | + ((green & 0xFF) << 8) | + (blue & 0xFF); + } + + public int getRed() { + return (value >> 16) & 0xFF; + } + + public int getGreen() { + return (value >> 8) & 0xFF; + } + + public int getBlue() { + return value & 0xFF; + } + + public int getAlpha() { + return (value >> 24) & 0xff; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof GridColor && value == ((GridColor) obj).value; + } + + @Override + public int hashCode() { + return value; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java new file mode 100644 index 0000000000000000000000000000000000000000..0515ded9b5bf94c49d13a8092c7063d0fbaee6bf --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java @@ -0,0 +1,133 @@ +/* + * 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.device; + +/** + * Abstract device that can draw primitive shapes and text. All sizes and coordinates are specified + * in inches and angles in radians unless stated otherwise. + */ +public interface GridDevice { + int DEFAULT_WIDTH = 720; + int DEFAULT_HEIGHT = 720; + + void openNewPage(); + + /** + * If the device is capable of buffering, calling {@code hold} should start buffering, e.g. + * nothing is displayed on the device, until {@link #flush()} is called. + */ + default void hold() { + } + + /** + * Should display the whole buffer at once. + * + * @see #hold() + */ + default void flush() { + } + + /** + * Gets called when the device is closed from R. This is the point where non-interactive devices + * should save their output into a file. + * + * @throws DeviceCloseException if the closing was not successful e.g. because the file could + * not be written. + */ + default void close() throws DeviceCloseException { + } + + /** + * Draws a rectangle at given position, the center of the rotation should be the center of the + * rectangle. The rotation is given in radians. + */ + void drawRect(DrawingContext ctx, double leftX, double bottomY, double width, double height, double rotationAnticlockWise); + + /** + * Connects given points with a line, there has to be at least two points in order to actually + * draw something. + */ + void drawPolyLines(DrawingContext ctx, double[] x, double[] y, int startIndex, int length); + + /** + * Version of {@link #drawPolyLines(DrawingContext, double[], double[], int, int)}, which should + * fill in the area bounded by the lines. Note that it is responsibility of the caller to + * connect the first and the last point if the caller wishes to draw actual polygon. + * + * @see DrawingContext#getFillColor() + */ + void drawPolygon(DrawingContext ctx, double[] x, double[] y, int startIndex, int length); + + void drawCircle(DrawingContext ctx, double centerX, double centerY, double radius); + + /** + * Prints a string with left bottom corner at given position rotated by given angle anti clock + * wise, the centre of the rotation should be the bottom left corer. + */ + void drawString(DrawingContext ctx, double leftX, double bottomY, double rotationAnticlockWise, String text); + + /** + * @return The width of the device in inches. + */ + double getWidth(); + + /** + * @return The height of the device in inches. + */ + double getHeight(); + + /** + * May change the default values the of the initial drawing context instance. Must return + * non-null value. + */ + default DrawingContextDefaults getDrawingContextDefaults() { + return new DrawingContextDefaults(); + } + + double getStringWidth(DrawingContext ctx, String text); + + /** + * Gets the height of a line of text in inches. This should include ascent and descent, i.e. + * from the very bottom to the very top of the tallest letter(s). The text is guaranteed to not + * contain any new lines. + */ + double getStringHeight(DrawingContext ctx, String text); + + final class DeviceCloseException extends Exception { + private static final long serialVersionUID = 1182697755931636214L; + + public DeviceCloseException(Throwable cause) { + super(cause); + } + + @Override + public String getMessage() { + return getCause().getMessage(); + } + + @Override + public synchronized Throwable fillInStackTrace() { + return this; + } + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/EmptyTypeSystemFlatLayout.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/ImageSaver.java similarity index 67% rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/EmptyTypeSystemFlatLayout.java rename to com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/ImageSaver.java index 63903c8fcb91bd1a727bbf14770a2cc0b2c8a527..7377c90be20238f0d8edb961100e82e531b2d64e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/EmptyTypeSystemFlatLayout.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/ImageSaver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,18 +20,15 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.nodes; +package com.oracle.truffle.r.library.fastrGrid.device; -import static com.oracle.truffle.api.dsl.internal.DSLOptions.DSLGenerator.FLAT; - -import com.oracle.truffle.api.dsl.TypeSystem; -import com.oracle.truffle.api.dsl.internal.DSLOptions; +import java.io.IOException; /** - * Auxiliary class for nodes that want to use the new DSL layout with no implicit type conversions. + * Devices that support saving their current state into a file should implement this interface. + * Note: this only makes sense for interactive devices. Devices like SVG are already saving into a + * file. */ -@TypeSystem -@DSLOptions(defaultGenerator = FLAT) -public class EmptyTypeSystemFlatLayout { - // empty +public interface ImageSaver { + void save(String path, String fileType) throws IOException; } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java new file mode 100644 index 0000000000000000000000000000000000000000..baad5ebe4167fd56f54527f64d3d811909de6fff --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java @@ -0,0 +1,273 @@ +/* + * 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.device; + +import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GRID_LINE_BLANK; +import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_TO_POINTS_FACTOR; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.text.DecimalFormat; +import java.util.Collections; + +import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridFontStyle; +import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineEnd; +import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineJoin; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.Utils; + +public class SVGDevice implements GridDevice { + private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.000"); + private final StringBuilder data = new StringBuilder(1024); + private final String filename; + private final double width; + private final double height; + + private DrawingContext cachedCtx; + + public SVGDevice(String filename, double width, double height) { + this.filename = filename; + this.width = width; + this.height = height; + } + + public String closeAndGetContents() { + closeSVGDocument(); + return data.toString(); + } + + @Override + public void openNewPage() { + // We stay compatible with GnuR: opening new page wipes out what has been drawn without + // saving it anywhere. + data.setLength(0); + cachedCtx = null; + append("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">"); + // we could use real inches, but that makes the output different to GnuR and other formats + // (jpg, ...), which use conversion 70px ~ 1in + append("<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' width='%.3fpx' height='%.3fpx' viewBox='0 0 %.3f %.3f'>", width * 70d, height * 70d, + width, + height); + } + + @Override + public void close() throws DeviceCloseException { + closeSVGDocument(); + try { + Files.write(Paths.get(filename), Collections.singleton(data.toString()), StandardCharsets.UTF_8); + } catch (IOException e) { + throw new DeviceCloseException(e); + } + } + + @Override + public void drawRect(DrawingContext ctx, double leftX, double bottomY, double width, double height, double rotationAnticlockWise) { + appendStyle(ctx); + append("<rect vector-effect='non-scaling-stroke' x='%.3f' y='%.3f' width='%.3f' height='%.3f'", leftX, transY(bottomY + height), width, height); + if (rotationAnticlockWise != 0) { + append("transform='rotate(%.3f %.3f,%.3f)'", toDegrees(rotationAnticlockWise), (leftX + width / 2.), transY(bottomY + height / 2.)); + } + data.append("/>"); // end of 'rect' tag + } + + @Override + public void drawPolyLines(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) { + drawPoly(ctx, x, y, startIndex, length, "style='fill:transparent'"); + } + + @Override + public void drawPolygon(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) { + drawPoly(ctx, x, y, startIndex, length, ""); + } + + @Override + public void drawCircle(DrawingContext ctx, double centerX, double centerY, double radius) { + appendStyle(ctx); + append("<circle vector-effect='non-scaling-stroke' cx='%.3f' cy='%.3f' r='%.3f'/>", centerX, transY(centerY), radius); + } + + @Override + public void drawString(DrawingContext ctx, double leftX, double bottomY, double rotationAnticlockWise, String text) { + appendStyle(ctx); + append("<text x='%.3f' y='%.3f' textLength='%.3f' lengthAdjust='spacingAndGlyphs' ", leftX, transY(bottomY), getStringWidth(ctx, text)); + // SVG interprets the "fill" as the color of the text + data.append("style='").append(getStyleColor("fill", ctx.getColor())).append(";stroke:transparent'"); + if (rotationAnticlockWise != 0) { + append(" transform='rotate(%.3f %.3f,%.3f)'", toDegrees(rotationAnticlockWise), leftX, transY(bottomY)); + } + data.append(">").append(text).append("</text>"); + } + + @Override + public double getWidth() { + return width; + } + + @Override + public double getHeight() { + return height; + } + + @Override + public double getStringWidth(DrawingContext ctx, String text) { + // The architecture of the GridDevice and grid package requires the devices be able to + // calculate the width of given string, this way one can e.g. create a box around text. SVG + // supports this by means of "textLength" attribute, which allows us to force text to have + // specified width. So we approximate the width of given text in the calculation below and + // then force the text to actually have such width if it ever gets displayed by #drawString. + double factor = 0.5; // empirically chosen + if (ctx.getFontStyle() == GridFontStyle.BOLD || ctx.getFontStyle() == GridFontStyle.BOLDITALIC) { + factor = 0.62; + } + double letterWidth = (ctx.getFontSize() / INCH_TO_POINTS_FACTOR); + double result = factor * (double) text.length() * letterWidth; + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + if (c == 'w' || c == 'm') { + result += letterWidth * 0.2; + } else if (c == 'z') { + result += letterWidth * 0.1; + } + } + return result; + } + + @Override + public double getStringHeight(DrawingContext ctx, String text) { + // we need height without ascent/descent of letters that are not in the string, this is + // empirically tested calculation + return 0.8 * (ctx.getFontSize() / INCH_TO_POINTS_FACTOR); + } + + private void drawPoly(DrawingContext ctx, double[] x, double[] y, int startIndex, int length, String attributes) { + appendStyle(ctx); + data.append("<polyline vector-effect='non-scaling-stroke' points='"); + for (int i = 0; i < length; i++) { + data.append(DECIMAL_FORMAT.format(x[i + startIndex])); + data.append(','); + data.append(DECIMAL_FORMAT.format(transY(y[i + startIndex]))); + data.append(' '); + } + data.append("' ").append(attributes).append(" />"); + } + + private void closeSVGDocument() { + if (cachedCtx != null) { + // see #appendStyle + append("</g>"); + } + append("</svg>"); + } + + private void appendStyle(DrawingContext ctx) { + if (cachedCtx == null || !DrawingContext.areSame(cachedCtx, ctx)) { + if (cachedCtx != null) { + append("</g>"); // close the previous style definition + } + append("<g style='"); + appendStyleUncached(ctx); + append("'>"); + } + cachedCtx = ctx; + } + + private void appendStyleUncached(DrawingContext ctx) { + byte[] lineType = ctx.getLineType(); + if (lineType == GRID_LINE_BLANK) { + append("stroke:transparent"); + } else { + append(getStyleColor("stroke", ctx.getColor())); + } + data.append(';').append(getStyleColor("fill", ctx.getFillColor())); + data.append(";stroke-width:").append(ctx.getLineWidth()); + if (lineType != DrawingContext.GRID_LINE_SOLID && lineType != DrawingContext.GRID_LINE_BLANK) { + data.append(";stroke-dasharray:"); + for (int i = 0; i < lineType.length; i++) { + data.append(lineType[i]); + if (i != lineType.length - 1) { + data.append(','); + } + } + } + data.append(";stroke-linejoin:").append(getSVGLineJoin(ctx.getLineJoin())); + data.append(";stroke-linecap:").append(getSVGLineCap(ctx.getLineEnd())); + if (ctx.getLineJoin() == GridLineJoin.MITRE) { + data.append(";stroke-miterlimit:").append(ctx.getLineMitre()); + } + data.append(";font-size:").append(ctx.getFontSize() / INCH_TO_POINTS_FACTOR).append("px"); + if (!ctx.getFontFamily().isEmpty()) { + // Font-family strings 'mono', 'sans', and 'serif' are OK for us + data.append(";font-family:").append(ctx.getFontFamily()); + } + if (ctx.getFontStyle().isBold()) { + data.append(";font-weight:bold"); + } + if (ctx.getFontStyle().isItalic()) { + data.append(";font-style:italic"); + } + } + + private static String getSVGLineCap(GridLineEnd lineEnd) { + switch (lineEnd) { + case ROUND: + return "round"; + case BUTT: + return "butt"; + case SQUARE: + return "square"; + default: + throw RInternalError.shouldNotReachHere("Unexpected value of GridLineEnd enum."); + } + } + + private static String getSVGLineJoin(GridLineJoin lineJoin) { + switch (lineJoin) { + case ROUND: + return "round"; + case MITRE: + return "miter"; + case BEVEL: + return "bevel"; + default: + throw RInternalError.shouldNotReachHere("Unexpected value of GridLineJoin enum."); + } + } + + private static String getStyleColor(String prefix, GridColor color) { + return Utils.stringFormat("%s:rgb(%d,%d,%d);%s-opacity:%.3f", prefix, color.getRed(), color.getGreen(), color.getBlue(), prefix, color.getAlpha() / 255d); + } + + private void append(String fmt, Object... args) { + data.append(Utils.stringFormat(fmt + "\n", args)); + } + + private double transY(double y) { + return (height - y); + } + + private static double toDegrees(double rotationAnticlockWise) { + return (180. / Math.PI) * -rotationAnticlockWise; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedImageDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedImageDevice.java new file mode 100644 index 0000000000000000000000000000000000000000..577784461859f69a3c600497f361c1f5b141dd17 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedImageDevice.java @@ -0,0 +1,86 @@ +/* + * 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.device.awt; + +import static java.awt.image.BufferedImage.TYPE_INT_RGB; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; + +public final class BufferedImageDevice extends Graphics2DDevice { + private final BufferedImage image; + private final String filename; + private final String fileType; + + private BufferedImageDevice(String filename, String fileType, BufferedImage image, Graphics2D graphics, int width, int height) { + super(graphics, width, height, true); + this.filename = filename; + this.fileType = fileType; + this.image = image; + graphics.setBackground(new Color(255, 255, 255)); + graphics.clearRect(0, 0, width, height); + } + + public static BufferedImageDevice open(String filename, String fileType, int width, int height) throws NotSupportedImageFormatException { + if (!isSupportedFormat(fileType)) { + throw new NotSupportedImageFormatException(); + } + BufferedImage image = new BufferedImage(width, height, TYPE_INT_RGB); + Graphics2D graphics = (Graphics2D) image.getGraphics(); + defaultInitGraphics(graphics); + return new BufferedImageDevice(filename, fileType, image, graphics, width, height); + } + + @Override + public void close() throws DeviceCloseException { + try { + ImageIO.write(image, fileType, new File(filename)); + } catch (IOException e) { + throw new DeviceCloseException(e); + } + } + + private static boolean isSupportedFormat(String formatName) { + String[] formatNames = ImageIO.getWriterFormatNames(); + for (String n : formatNames) { + if (n.equals(formatName)) { + return true; + } + } + return false; + } + + public static class NotSupportedImageFormatException extends Exception { + private static final long serialVersionUID = 1182697755931636217L; + + @Override + public synchronized Throwable fillInStackTrace() { + return this; + } + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedJFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedJFrameDevice.java new file mode 100644 index 0000000000000000000000000000000000000000..607b0ad8b033aca74cbdcc07b9d807e45b5cee5a --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedJFrameDevice.java @@ -0,0 +1,196 @@ +/* + * 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.device.awt; + +import static java.awt.image.BufferedImage.TYPE_INT_RGB; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.image.BufferStrategy; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; + +import javax.imageio.ImageIO; + +import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.library.fastrGrid.device.ImageSaver; + +/** + * Decorator for {@link JFrameDevice} that implements {@link #hold()} and {@link #flush()} + * functionality and implements the {@link ImageSaver} device. + * + * Methods {@link #hold()} and {@link #flush()} open/draw a 2D graphics buffer, while the buffer is + * open, any drawing is done in the buffer not on the screen and the buffer is dumped to the screen + * once {@link #flush()} is called. + * + * We also record any drawing code to be able to replay it if the buffer happens to loose its + * contents, which is a possibility mentioned in the documentation. Moreover, this record of drawing + * can be used in {@link #save(String, String)} to replay the drawing in a {@code BufferedImage}. + * Note: here we rely on the fact that {@link DrawingContext} is immutable. + */ +public final class BufferedJFrameDevice implements GridDevice, ImageSaver { + private final JFrameDevice inner; + private final ArrayList<Runnable> drawActions = new ArrayList<>(200); + private BufferStrategy buffer; + + public BufferedJFrameDevice(JFrameDevice inner) { + this.inner = inner; + } + + @Override + public void openNewPage() { + inner.openNewPage(); + drawActions.clear(); + if (buffer != null) { + // if new page is opened while we are on hold, we should throw away current buffer. In + // other words that is like starting new hold without previous flush. + buffer.dispose(); + buffer = null; + hold(); + } + } + + @Override + public void hold() { + if (buffer != null) { + return; // already buffering + } + buffer = inner.getCurrentFrame().getBufferStrategy(); + if (buffer == null) { + inner.getCurrentFrame().createBufferStrategy(2); + buffer = inner.getCurrentFrame().getBufferStrategy(); + } + drawActions.clear(); + setGraphics(buffer.getDrawGraphics()); + } + + @Override + public void flush() { + if (buffer == null) { + return; + } + + buffer.show(); + // re-draw the buffer if the contents were lost + while (buffer.contentsLost()) { + setGraphics(buffer.getDrawGraphics()); + for (Runnable drawAction : drawActions) { + drawAction.run(); + } + buffer.show(); + } + + setGraphics(inner.getCurrentFrame().getGraphics()); + buffer.dispose(); + buffer = null; + } + + @Override + public void close() throws DeviceCloseException { + inner.close(); + } + + @Override + public void drawRect(DrawingContext ctx, double leftX, double bottomY, double width, double height, double rotationAnticlockWise) { + inner.drawRect(ctx, leftX, bottomY, width, height, rotationAnticlockWise); + drawActions.add(() -> inner.drawRect(ctx, leftX, bottomY, width, height, rotationAnticlockWise)); + } + + @Override + public void drawPolyLines(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) { + inner.drawPolyLines(ctx, x, y, startIndex, length); + double[] xCopy = new double[x.length]; + double[] yCopy = new double[y.length]; + System.arraycopy(x, 0, xCopy, 0, x.length); + System.arraycopy(y, 0, yCopy, 0, y.length); + drawActions.add(() -> inner.drawPolyLines(ctx, xCopy, yCopy, startIndex, length)); + } + + @Override + public void drawPolygon(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) { + inner.drawPolygon(ctx, x, y, startIndex, length); + double[] xCopy = new double[x.length]; + double[] yCopy = new double[y.length]; + System.arraycopy(x, 0, xCopy, 0, x.length); + System.arraycopy(y, 0, yCopy, 0, y.length); + drawActions.add(() -> inner.drawPolygon(ctx, xCopy, yCopy, startIndex, length)); + } + + @Override + public void drawCircle(DrawingContext ctx, double centerX, double centerY, double radius) { + inner.drawCircle(ctx, centerX, centerY, radius); + drawActions.add(() -> inner.drawCircle(ctx, centerX, centerY, radius)); + } + + @Override + public void drawString(DrawingContext ctx, double leftX, double bottomY, double rotationAnticlockWise, String text) { + inner.drawString(ctx, leftX, bottomY, rotationAnticlockWise, text); + drawActions.add(() -> inner.drawString(ctx, leftX, bottomY, rotationAnticlockWise, text)); + } + + @Override + public double getWidth() { + return inner.getWidth(); + } + + @Override + public double getHeight() { + return inner.getHeight(); + } + + @Override + public double getStringWidth(DrawingContext ctx, String text) { + return inner.getStringWidth(ctx, text); + } + + @Override + public double getStringHeight(DrawingContext ctx, String text) { + return inner.getStringHeight(ctx, text); + } + + @Override + public void save(String path, String fileType) throws IOException { + int realWidth = (int) (getWidth() * JFrameDevice.AWT_POINTS_IN_INCH); + int readHeight = (int) (getHeight() * JFrameDevice.AWT_POINTS_IN_INCH); + BufferedImage image = new BufferedImage(realWidth, readHeight, TYPE_INT_RGB); + Graphics2D imageGraphics = (Graphics2D) image.getGraphics(); + imageGraphics.setBackground(new Color(255, 255, 255)); + imageGraphics.clearRect(0, 0, realWidth, readHeight); + setGraphics(imageGraphics); + for (Runnable drawAction : drawActions) { + drawAction.run(); + } + ImageIO.write(image, fileType, new File(path)); + setGraphics(inner.getCurrentFrame().getGraphics()); + } + + private void setGraphics(Graphics graphics) { + Graphics2DDevice.defaultInitGraphics((Graphics2D) graphics); + inner.getGraphics2D().dispose(); + inner.setGraphics2D((Graphics2D) graphics); + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java new file mode 100644 index 0000000000000000000000000000000000000000..90bf1adc20281dd8002220b8599c20c35214d8ea --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java @@ -0,0 +1,339 @@ +/* + * 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.device.awt; + +import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_TO_POINTS_FACTOR; +import static java.awt.geom.Path2D.WIND_EVEN_ODD; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Path2D; +import java.awt.geom.Rectangle2D; + +import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext; +import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridFontStyle; +import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineEnd; +import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineJoin; +import com.oracle.truffle.r.library.fastrGrid.device.GridColor; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.runtime.RInternalError; + +/** + * A device that draws to given {@code Graphics2D} object regardless of whether it was created for + * e.g. an image, or window. This device only used by other devices and not exposed at the R level. + * Note: it is responsibility of the use to handle resources management, i.e. calling + * {@code dispose} on the graphics object once it is not needed anymore. + */ +public class Graphics2DDevice implements GridDevice { + // Grid's coordinate system has origin in left bottom corner and y axis grows from bottom to + // top. Moreover, the grid system uses inches as units. We do not use builtin transformations, + // because (a) text rendering gets affected badly (upside down text), (b) the user of this call + // may wish to apply his/her own transformations to the graphics object and we should not + // interfere with these. In cases we do use transformation, we make sure to set back the + // original one after we're done. + static final double AWT_POINTS_IN_INCH = 72.; + + private static BasicStroke blankStroke; + + private final int width; + private final int height; + private Graphics2D graphics; + private final boolean graphicsIsExclusive; + private DrawingContext cachedContext; + + /** + * @param graphics Object that should be used for the drawing. + * @param width Width of the drawing area in AWT units. + * @param height Height of the drawing area in AWT units. + * @param graphicsIsExclusive If the graphics object is exclusively used for drawing only by + * this class, then it can optimize some things. + */ + public Graphics2DDevice(Graphics2D graphics, int width, int height, boolean graphicsIsExclusive) { + initStrokes(); + setGraphics2D(graphics); + this.width = width; + this.height = height; + this.graphicsIsExclusive = graphicsIsExclusive; + } + + static void defaultInitGraphics(Graphics2D graphics) { + graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); + } + + @Override + public void openNewPage() { + graphics.clearRect(0, 0, getWidthAwt(), getHeightAwt()); + } + + @Override + public void drawRect(DrawingContext ctx, double leftXIn, double bottomYIn, double widthIn, double heightIn, double rotationAnticlockWise) { + int leftX = transX(leftXIn); + int topY = transY(bottomYIn + heightIn); + int width = transDim(widthIn); + int height = transDim(heightIn); + setContext(ctx); + if (rotationAnticlockWise == 0.) { + drawShape(ctx, new Rectangle2D.Double(leftX, topY, width, height)); + return; + } + transformed(leftX + width / 2, topY + height / 2, rotationAnticlockWise, () -> drawShape(ctx, new Rectangle2D.Double(-(width / 2), -(height / 2), width, height))); + } + + @Override + public void drawPolyLines(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) { + Path2D.Double path = getPath2D(x, y, startIndex, length); + setContext(ctx); + graphics.draw(path); + } + + @Override + public void drawPolygon(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) { + Path2D.Double path = getPath2D(x, y, startIndex, length); + setContext(ctx); + drawShape(ctx, path); + } + + @Override + public void drawCircle(DrawingContext ctx, double centerXIn, double centerYIn, double radiusIn) { + setContext(ctx); + int centerX = transX(centerXIn); + int centerY = transY(centerYIn); + int radius = transDim(radiusIn); + drawShape(ctx, new Ellipse2D.Double(centerX - radius, centerY - radius, radius * 2d, radius * 2d)); + } + + @Override + public void drawString(DrawingContext ctx, double leftXIn, double bottomYIn, double rotationAnticlockWise, String text) { + setContextAndFont(ctx); + int leftX = transX(leftXIn); + FontMetrics fontMetrics = graphics.getFontMetrics(graphics.getFont()); + int bottomY = transY(bottomYIn) - fontMetrics.getDescent(); + transformed(leftX, bottomY, rotationAnticlockWise, () -> graphics.drawString(text, 0, 0)); + } + + @Override + public double getWidth() { + return getWidthAwt() / AWT_POINTS_IN_INCH; + } + + @Override + public double getHeight() { + return getHeightAwt() / AWT_POINTS_IN_INCH; + } + + @Override + public double getStringWidth(DrawingContext ctx, String text) { + setContextAndFont(ctx); + int swingUnits = graphics.getFontMetrics(graphics.getFont()).stringWidth(text); + return swingUnits / AWT_POINTS_IN_INCH; + } + + @Override + public double getStringHeight(DrawingContext ctx, String text) { + setContextAndFont(ctx); + FontMetrics fontMetrics = graphics.getFontMetrics(graphics.getFont()); + double swingUnits = fontMetrics.getAscent() + fontMetrics.getDescent(); + return swingUnits / AWT_POINTS_IN_INCH; + } + + /** + * Allows to override the default fixed width behavior with dynamically computed width. + */ + int getWidthAwt() { + return width; + } + + /** + * Allows to override the default fixed height behavior with dynamically computed height. + */ + int getHeightAwt() { + return height; + } + + void setGraphics2D(Graphics2D newGraphics) { + assert newGraphics != null; + graphics = newGraphics; + } + + public Graphics2D getGraphics2D() { + return graphics; + } + + private int transY(double y) { + return getHeightAwt() - (int) (y * AWT_POINTS_IN_INCH); + } + + private static int transX(double x) { + return (int) (x * AWT_POINTS_IN_INCH); + } + + private static int transDim(double widthOrHeight) { + return (int) (widthOrHeight * AWT_POINTS_IN_INCH); + } + + private static void initStrokes() { + if (blankStroke != null) { + return; + } + blankStroke = new BasicStroke(0f); + } + + private void transformed(int centreX, int centreY, double radiansAnticlockwise, Runnable action) { + AffineTransform oldTransform = graphics.getTransform(); + AffineTransform newTr = new AffineTransform(oldTransform); + newTr.translate(centreX, centreY); + newTr.rotate(-radiansAnticlockwise); + graphics.setTransform(newTr); + action.run(); + graphics.setTransform(oldTransform); + } + + private Path2D.Double getPath2D(double[] x, double[] y, int startIndex, int length) { + assert startIndex >= 0 && startIndex < x.length && startIndex < y.length : "startIndex out of bounds"; + assert length > 0 && (startIndex + length) <= Math.min(x.length, y.length) : "length out of bounds"; + Path2D.Double path = new Path2D.Double(WIND_EVEN_ODD, x.length); + path.moveTo(transX(x[startIndex]), transY(y[startIndex])); + for (int i = startIndex + 1; i < length; i++) { + path.lineTo(transX(x[i]), transY(y[i])); + } + return path; + } + + private void drawShape(DrawingContext drawingCtx, Shape shape) { + Paint paint = graphics.getPaint(); + graphics.setPaint(fromGridColor(drawingCtx.getFillColor())); + graphics.fill(shape); + graphics.setPaint(paint); + graphics.draw(shape); + } + + private void setContext(DrawingContext ctx) { + if (graphicsIsExclusive && cachedContext == ctx) { + return; + } + graphics.setColor(fromGridColor(ctx.getColor())); + graphics.setStroke(getStrokeFromCtx(ctx)); + cachedContext = ctx; + } + + private void setContextAndFont(DrawingContext ctx) { + if (graphicsIsExclusive && cachedContext == ctx) { + return; + } + setContext(ctx); + float fontSize = (float) ((ctx.getFontSize() / INCH_TO_POINTS_FACTOR) * AWT_POINTS_IN_INCH); + Font font = new Font(getFontName(ctx.getFontFamily()), getAwtFontStyle(ctx.getFontStyle()), 1).deriveFont(fontSize); + graphics.setFont(font); + } + + // Transformation of DrawingContext data types to AWT constants + + private String getFontName(String gridFontFamily) { + if (gridFontFamily == null) { + return null; + } + switch (gridFontFamily) { + case DrawingContext.FONT_FAMILY_MONO: + return Font.MONOSPACED; + case DrawingContext.FONT_FAMILY_SANS: + return Font.SANS_SERIF; + case DrawingContext.FONT_FAMILY_SERIF: + return Font.SERIF; + case "": + return null; + } + return gridFontFamily; + } + + private int getAwtFontStyle(GridFontStyle fontStyle) { + switch (fontStyle) { + case PLAIN: + return Font.PLAIN; + case BOLD: + return Font.BOLD; + case ITALIC: + return Font.ITALIC; + case BOLDITALIC: + return Font.BOLD | Font.ITALIC; + default: + throw RInternalError.shouldNotReachHere("unexpected value of GridFontStyle enum"); + } + } + + private static Color fromGridColor(GridColor color) { + return new Color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); + } + + private BasicStroke getStrokeFromCtx(DrawingContext ctx) { + byte[] type = ctx.getLineType(); + double width = ctx.getLineWidth(); + int lineJoin = fromGridLineJoin(ctx.getLineJoin()); + float lineMitre = (float) ctx.getLineMitre(); + int endCap = fromGridLineEnd(ctx.getLineEnd()); + if (type == DrawingContext.GRID_LINE_BLANK) { + return blankStroke; + } else if (type == DrawingContext.GRID_LINE_SOLID) { + return new BasicStroke((float) (width), endCap, lineJoin, lineMitre); + } + float[] pattern = new float[type.length]; + for (int i = 0; i < pattern.length; i++) { + pattern[i] = (float) (type[i]); + } + return new BasicStroke((float) (width), endCap, lineJoin, lineMitre, pattern, 0f); + } + + private static int fromGridLineEnd(GridLineEnd lineEnd) { + switch (lineEnd) { + case ROUND: + return BasicStroke.CAP_ROUND; + case BUTT: + return BasicStroke.CAP_BUTT; + case SQUARE: + return BasicStroke.CAP_SQUARE; + default: + throw RInternalError.shouldNotReachHere("unexpected value of GridLineEnd enum"); + } + } + + private static int fromGridLineJoin(GridLineJoin lineJoin) { + switch (lineJoin) { + case BEVEL: + return BasicStroke.JOIN_BEVEL; + case MITRE: + return BasicStroke.JOIN_MITER; + case ROUND: + return BasicStroke.JOIN_ROUND; + default: + throw RInternalError.shouldNotReachHere("unexpected value of GridLineJoin enum"); + } + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java new file mode 100644 index 0000000000000000000000000000000000000000..b9faaaa9ffbda0758f11f75e2f2a8b268917f2f5 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java @@ -0,0 +1,166 @@ +/* + * 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.device.awt; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.HeadlessException; +import java.awt.Toolkit; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.Timer; +import java.util.TimerTask; + +import javax.swing.JFrame; +import javax.swing.JPanel; + +public final class JFrameDevice extends Graphics2DDevice { + + private final JFrame currentFrame; + private final boolean disposeResources; + private Runnable onResize; + + /** + * @param frame The frame that should be used for drawing. + * @param graphics The graphics object that should be used for drawing. This constructor + * overload allows to initialize the graphics object. + * @param disposeResources Should the frame and graphics objects be disposed at {@link #close()} + * . + */ + private JFrameDevice(JFrame frame, Graphics2D graphics, boolean disposeResources) { + super(graphics, frame.getContentPane().getWidth(), frame.getContentPane().getHeight(), true); + currentFrame = frame; + this.disposeResources = disposeResources; + if (currentFrame instanceof FastRFrame) { + ((FastRFrame) currentFrame).device = this; + } + } + + /** + * Creates a standalone device that manages the window itself and closes it once + * {@link #close()} gets called. + */ + public static JFrameDevice create(int width, int height) { + FastRFrame frame = new FastRFrame(width, height); + frame.setVisible(true); + frame.pack(); + Graphics2D graphics = (Graphics2D) frame.getGraphics(); + defaultInitGraphics(graphics); + return new JFrameDevice(frame, graphics, true); + } + + @Override + public void close() throws DeviceCloseException { + if (disposeResources) { + getGraphics2D().dispose(); + currentFrame.dispose(); + } + } + + @Override + int getWidthAwt() { + return currentFrame.getContentPane().getWidth(); + } + + @Override + int getHeightAwt() { + return currentFrame.getContentPane().getHeight(); + } + + public void setResizeListener(Runnable onResize) { + this.onResize = onResize; + } + + JFrame getCurrentFrame() { + return currentFrame; + } + + static class FastRFrame extends JFrame { + private static final long serialVersionUID = 1L; + private final JPanel fastRComponent = new JPanel(); + private JFrameDevice device; + + volatile boolean resizeScheduled = false; + private int oldWidth; + private int oldHeight; + private final Timer timer = new Timer(); + + FastRFrame(int width, int height) throws HeadlessException { + super("FastR"); + addListeners(); + createUI(width, height); + center(); + oldWidth = width; + oldHeight = height; + } + + private void createUI(int width, int height) { + setLayout(new BorderLayout()); + setSize(new Dimension(width, height)); + add(fastRComponent, BorderLayout.CENTER); + fastRComponent.setPreferredSize(getSize()); + } + + private void addListeners() { + addWindowFocusListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + dispose(); + } + }); + addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + if (oldHeight == getHeight() && oldWidth == getWidth()) { + return; + } + if (!resizeScheduled) { + resizeScheduled = true; + timer.schedule(new TimerTask() { + @Override + public void run() { + oldWidth = getWidth(); + oldHeight = getHeight(); + resizeScheduled = false; + if (device.onResize != null) { + device.onResize.run(); + } + } + }, 1000); + } + } + }); + } + + private void center() { + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + Dimension frameSize = getSize(); + int x = (screenSize.width - frameSize.width) / 2; + int y = (screenSize.height - frameSize.height) / 2; + setLocation(x, y); + } + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R new file mode 100644 index 0000000000000000000000000000000000000000..068c5fb4f50a1c2eb42ef574881321d47aee4db3 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R @@ -0,0 +1,214 @@ +# +# 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) 2001-3 Paul Murrell +# Copyright (c) 1998-2015, The R Core Team +# Copyright (c) 2017, Oracle and/or its affiliates +# +# All rights reserved. +# + +# This file contains internal R helper functions that are invoked from grid externals implementations. +# Where original grid implementation uses many Rf_eval calls to call back to R, we rewrite the whole +# logic to R. Some functions implement whole externals, like L_downvppath, some implement coherent +# parts of the logic and the rest is in Java. + +# Used by the interactive device to redraw the whole scene if the window gets resized. +redrawAll <- function() { + popViewport(0, recording = FALSE) + grid:::draw.all() +} + +# chull from grDevices package is used in EdgeDetection.java +# Note: chull calls to native function, which we may consider +# porting or calling directly in the future. +chullWrapper <- function(x, y) { + library(grDevices) + grDevices:::chull(x, y) +} + +# Returns list with elements [[1]] - depth, zero if not found, [[2]] - the viewport, NULL if not found +# We are searching for child "name" in "pvp", if the "path" is not integer value 0, +# then also pathMatch(path, currPath) must hold. +find.viewport <- function(path, name, strict, currPath, pvp, depth) { + if (length(ls(env=pvp$children)) == 0) { + return(list(FALSE, NULL)) + } else if (exists(name, env=pvp$children, inherits=FALSE) && (path == 0L || grid:::pathMatch(path, currPath, strict))) { + return(list(depth, get(name, env=pvp$children, inherits=FALSE))) + } else if (strict && path == 0L) { + return(list(FALSE, NULL)) + } else { + return(find.in.children(path, name, strict, currPath, pvp$children, depth + 1L)) + } +} + +find.in.children <- function(path, name, strict, currPath, children, depth) { + cpvps <- ls(env=children) + ncpvp <- length(cpvps) + count <- 0L + found <- FALSE + while (count < ncpvp && !found) { + child <- get(cpvps[count + 1L], env=children) + nextCurrPath <- if (path == 0L) NULL else grid:::growPath(currPath, child$name) + result <- find.viewport(path, name, strict, nextCurrPath, child, depth) + if (result[[1L]]) { + return(result); + } + count <- count + 1L + } + list(FALSE, NULL) # not found +} + +# path is a string, e.g. "A::B::C", or NULL if we are not searching for particular path +# name is a string, the name of child we are looking for +L_downvppath <- function(path, name, strict) { + currVp <- .Call(grid:::L_currentViewport) + result <- find.viewport(path, name, strict, NULL, currVp, 1L); + if (result[[1]]) { + .Internal(.fastr.grid.doSetViewPort(result[[2L]], FALSE, FALSE)); + return(result[[1L]]) + } else { + stop(paste0("Viewport '", name, "' was not found")); + } +} + +L_downviewport <- function(name, strict) { + L_downvppath(0L, name, strict) +} + +L_setviewport <- function(vp, hasParent) { + pushedVP <- grid:::pushedvp(vp); + .Internal(.fastr.grid.doSetViewPort(pushedVP, hasParent, TRUE)); +} + +L_unsetviewport <- function(n) { + gvp <- .Call(grid:::L_currentViewport) + newVp <- gvp; + for (i in 1:n) { + gvp <- newVp; + newVp <- gvp$parent; + if (is.null(newVp)) { + error("cannot pop the top-level viewport ('grid' and 'graphics' output mixed?)") + } + } + # remove +} + +################################################### +# Helper functions to deal with null and grob units +# these functions are invoked from Java directly + +# Should be in sync with constants in Unit java class +L_GROBX <- 19 +L_GROBY <- 20 +L_GROBWIDTH <- 21 +L_GROBHEIGHT <- 22 +L_GROBASCENT <- 23 +L_GROBDESCENT <- 24 + +indexMod <- function(i, mod) ((i - 1) %% mod) + 1 + +# if the grob is gPath, use it to find an actual grob +# savedgrob - the grob from grid context +findGrob <- function(grob, savedgrob) { + if (inherits(grob, "gPath")) { + if (is.null(savedgrob)) { + return(grid:::findGrobinDL(grob$name)) + } else { + return(grid:::findGrobinChildren(grob$name, savedgrob$children)) + } + } + grob +} + +# this is called from FastR, it is simpler to implement this whole function in R. +# GnuR uses series of install -> lang2 -> eval calls to achieve this from C. +isPureNullUnit <- function(unit, index) { + if (inherits(unit, "unit.arithmetic")) { + return(isPureNullUnitArithmetic(unit, index)); + } else if (inherits(unit, "unit.list")) { + return(isPureNullUnit(unit[[indexMod(index, length(unit))]], 1)) + } + unitIdVec <- attr(unit, "valid.unit") + unitId <- unitIdVec[[indexMod(index, length(unitIdVec))]] + if (unitId == L_GROBWIDTH) { + return(isPureNullUnitGrobDim(unit, index, grid:::width)) + } else if (unitId == L_GROBHEIGHT) { + return(isPureNullUnitGrobDim(unit, index, grid:::height)) + } + unitId == 5 # L_NULL +} + +getUnitData <- function(unit, index) { + result <- attr(unit, "data") + if (!is.list(result)) { + return(result) + } + result[[indexMod(index, length(result))]] +} + +isPureNullUnitGrobDim <- function(unit, index, dimFunction) { + # Can a grob have "null" width/height? + # to be sure we cover everything, we keep the check here (like in GnuR) + savedgpar <- .Call(grid:::L_getGPar) + savedgrob <- .Call(grid:::L_getCurrentGrob) + + grob <- findGrob(getUnitData(unit, index), savedgrob) + + updatedgrob <- grid:::preDraw(grob) + result <- isPureNullUnit(dimFunction(updatedgrob), 1) + grid:::postDraw(updatedgrob) + + .Call(grid:::L_setGPar, savedgpar) + .Call(grid:::L_setCurrentGrob, savedgrob) + result +} + +isPureNullUnitArithmetic <- function(x, index) { + if (x$fname %in% c('+', '-')) { + # can this ever happen when Ops.unit raises error for two null units added/subtracted? + # to be sure we cover everything, we keep the check here (like in GnuR) + return(isPureNullUnit(x$arg1, index) && isPureNullUnit(x$arg2, index)) + } else if (x$fname == '*') { + return(isPureNullUnit(x$arg2, index)) + } else if (x$fname %in% c('min', 'max', 'sum')) { + return(all(sapply(seq_along(x$arg1), function(i) isPureNullUnit(x$arg1, i)))) + } else { + error("unimplemented unit function"); + } +} + +# tests: +# isPureNullUnit(grid:::unit.list(unit(c(1,2,3),c('mm', 'cm', 'null'))), 1) == FALSE +# isPureNullUnit(grid:::unit.list(unit(c(1,2,3),c('mm', 'cm', 'null'))), 3) == TRUE +# isPureNullUnit(3*unit(1,'mm'), 2) == FALSE +# isPureNullUnit(3*unit(1,'null'), 2) == TRUE +# isPureNullUnit(min(unit(1,'null')), 1) == TRUE +# { gt <- grid.text("Hi there"); isPureNullUnit(unit(1, "grobwidth", gt), 1) } == FALSE +# { gt <- grid.text("Hi there"); isPureNullUnit(unit(1, "grobheight", gt), 1) } == FALSE + +grobConversionPreDraw <- function(grobIn) { + grob <- findGrob(grobIn, .Call(grid:::L_getCurrentGrob)) + grid:::preDraw(grob) +} + +grobConversionGetUnitXY <- function(grob, unitId, theta) { + if (unitId == L_GROBX || unitId == L_GROBY) { + return(list(grid:::xDetails(grob, theta), grid:::yDetails(grob, theta))) + } else if (unitId == L_GROBWIDTH) { + return(list(grid:::width(grob))) + } else if (unitId == L_GROBHEIGHT) { + return(list(grid:::height(grob))) + } else if (unitId == L_GROBDESCENT) { + return(list(grid:::descentDetails(grob))) + } else if (unitId == L_GROBASCENT) { + return(list(grid:::ascentDetails(grob))) + } + error("grobConversionGetUnitXY: not a grob unit.") +} + +grobConversionPostDraw <- function(grob) { + grid:::postDraw(grob) +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java new file mode 100644 index 0000000000000000000000000000000000000000..6ae4427041d6d613254cd87fdb1f0ba971e8d5ad --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java @@ -0,0 +1,54 @@ +/* + * 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.grDevices; + +import com.oracle.truffle.r.library.fastrGrid.GridContext; +import com.oracle.truffle.r.library.fastrGrid.device.SVGDevice; +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.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RNull; + +public class DevCairo extends RExternalBuiltinNode { + static { + Casts.noCasts(DevCairo.class); + } + + @Override + protected Object call(RArgsValuesAndNames args) { + if (args.getLength() < 4) { + throw error(Message.ARGUMENTS_REQUIRED_COUNT, args.getLength(), "devCairo", 4); + } + + String filename = RRuntime.asString(args.getArgument(0)); + int witdh = RRuntime.asInteger(args.getArgument(2)); + int height = RRuntime.asInteger(args.getArgument(2)); + if (RRuntime.isNA(witdh) || RRuntime.isNA(height) || RRuntime.isNA(filename) || filename.isEmpty()) { + throw error(Message.INVALID_ARG_TYPE); + } + + GridContext.getContext().setCurrentDevice("svg", new SVGDevice(filename, (double) witdh / 72., (double) height / 72.)); + return RNull.instance; + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToStringVectorClosure.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCurr.java similarity index 54% rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToStringVectorClosure.java rename to com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCurr.java index 05de4164e67f745e31206532a276837652d4f3a9..5c9046e35dc561a4f13b74eb43bc67676f16c48c 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToStringVectorClosure.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCurr.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,24 +20,24 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.data.closures; +package com.oracle.truffle.r.library.fastrGrid.grDevices; -import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.library.fastrGrid.GridContext; +import com.oracle.truffle.r.library.fastrGrid.graphics.RGridGraphicsAdapter; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.data.RDataFactory; +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; -final class RIntToStringVectorClosure extends RToStringVectorClosure implements RAbstractStringVector { - - RIntToStringVectorClosure(RAbstractIntVector vector) { - super(vector); +public final class DevCurr extends RExternalBuiltinNode.Arg0 { + static { + Casts.noCasts(DevCurr.class); } @Override - public String getDataAt(int index) { - int data = ((RAbstractIntVector) vector).getDataAt(index); - if (!vector.isComplete() && RRuntime.isNA(data)) { - return RRuntime.STRING_NA; - } - return RRuntime.intToStringNoCheck(data); + public RAbstractIntVector execute() { + int index = GridContext.getContext().getCurrentDeviceIndex(); + RStringVector names = RDataFactory.createStringVectorFromScalar(RGridGraphicsAdapter.getDeviceName(index)); + return RDataFactory.createIntVector(new int[]{index + 1}, RDataFactory.COMPLETE_VECTOR, names); } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevHoldFlush.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevHoldFlush.java new file mode 100644 index 0000000000000000000000000000000000000000..853f82bcf3b07e76bb14ff163b5c5ce2c2e811cd --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevHoldFlush.java @@ -0,0 +1,61 @@ +/* + * 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.grDevices; + +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.library.fastrGrid.GridContext; +import com.oracle.truffle.r.library.fastrGrid.GridState; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; + +public abstract class DevHoldFlush extends RExternalBuiltinNode.Arg1 { + static { + Casts casts = new Casts(DevHoldFlush.class); + casts.arg(0).mustBe(numericValue()).asIntegerVector().findFirst(); + } + + public static DevHoldFlush create() { + return DevHoldFlushNodeGen.create(); + } + + @Specialization + @TruffleBoundary + int doInteger(int num) { + GridState gridState = GridContext.getContext().getGridState(); + int result = gridState.getDevHoldCount(); + if (num < 0) { + result = gridState.setDevHoldCount(Math.max(0, result + num)); + if (result == 0) { + GridContext.getContext().getCurrentDevice().flush(); + } + } else if (num > 0) { + if (result == 0) { + GridContext.getContext().getCurrentDevice().hold(); + } + result = gridState.setDevHoldCount(result + num); + } + return result; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevOff.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevOff.java new file mode 100644 index 0000000000000000000000000000000000000000..8dc3209f96b6485ca7ce3481e843442a03320cc2 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevOff.java @@ -0,0 +1,79 @@ +/* + * 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.grDevices; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.library.fastrGrid.GridContext; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice.DeviceCloseException; +import com.oracle.truffle.r.library.fastrGrid.device.SVGDevice; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.data.RNull; + +public abstract class DevOff extends RExternalBuiltinNode.Arg1 { + static { + Casts casts = new Casts(DevOff.class); + casts.arg(0).asIntegerVector().findFirst(); + } + + public static DevOff create() { + return DevOffNodeGen.create(); + } + + @Specialization + @TruffleBoundary + public Object devOff(int whichR) { + GridContext ctx = GridContext.getContext(); + int which = Math.abs(whichR) - 1; // convert to Java index + if (which < 0 || which >= ctx.getDevicesSize()) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Wrong device number."); + } + + // FastR specific special handling for SVG device, when the index is negative, return the + // SVG code + if (whichR < 0) { + return closeSvgDevice(ctx, which); + } + + try { + ctx.closeDevice(which); + } catch (DeviceCloseException e) { + throw error(Message.GENERIC, "Cannot close the device. Details: " + e.getMessage()); + } + return RNull.instance; + } + + private String closeSvgDevice(GridContext ctx, int which) { + GridDevice dev = ctx.getDevice(which); + ctx.removeDevice(which); + if ((dev instanceof SVGDevice)) { + return ((SVGDevice) dev).closeAndGetContents(); + } else { + warning(Message.GENERIC, "The device was not SVG device."); + return ""; + } + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java new file mode 100644 index 0000000000000000000000000000000000000000..9825b273c127b2caef56c0d77c931e95285ec364 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java @@ -0,0 +1,121 @@ +/* + * 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.grDevices; + +import static com.oracle.truffle.r.library.fastrGrid.WindowDevice.awtNotSupported; + +import java.awt.Graphics2D; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.java.JavaInterop; +import com.oracle.truffle.r.library.fastrGrid.GridContext; +import com.oracle.truffle.r.library.fastrGrid.WindowDevice; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedImageDevice; +import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedImageDevice.NotSupportedImageFormatException; +import com.oracle.truffle.r.library.fastrGrid.device.awt.Graphics2DDevice; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.FastRConfig; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RTypedValue; + +/** + * Node that handles the {@code C_X11} external calls. Those calls may be initiated from either the + * {@code X11}, {@code jpeg}, {@code bmp}, {@code png} functions and from FastR specific {@code awt} + * . The arguments determine which device should be opened. + */ +public final class InitWindowedDevice extends RExternalBuiltinNode { + + static { + Casts.noCasts(InitWindowedDevice.class); + } + + @Override + @TruffleBoundary + protected Object call(RArgsValuesAndNames args) { + if (!FastRConfig.InternalGridAwtSupport) { + throw awtNotSupported(); + } + + int width = getIntOrDefault(args, 1, GridDevice.DEFAULT_WIDTH); + int height = getIntOrDefault(args, 2, GridDevice.DEFAULT_HEIGHT); + + // if the first argument is a String, then it may describes the image format and filename to + // use, the format is e.g. "jpeg::quality:filename" + if (args.getLength() >= 1) { + String name = RRuntime.asString(args.getArgument(0)); + if (!RRuntime.isNA(name) && name.contains("::")) { + return openImageDevice(name, width, height); + } + } + + // otherwise the windowed device + // check if we got custom Graphics2D object as 3rd parameter + boolean isFastRDevice = args.getArgument(0).equals(".FASTR.AWT"); + if (isFastRDevice && args.getLength() > 3) { + Object arg3 = args.getArgument(3); + boolean isTruffleObj = arg3 instanceof TruffleObject && !(arg3 instanceof RTypedValue); + if (isTruffleObj && JavaInterop.isJavaObject(Graphics2D.class, (TruffleObject) arg3)) { + Graphics2D graphics = JavaInterop.asJavaObject(Graphics2D.class, (TruffleObject) arg3); + Graphics2DDevice device = new Graphics2DDevice(graphics, width, height, false); + GridContext.getContext().setCurrentDevice("awt", device); + return RNull.instance; + } else if (isTruffleObj) { + warning(Message.GENERIC, "3rd argument is foreign object, but not of type Graphics2D."); + } + } + + // otherwise create the window ourselves + GridDevice device = WindowDevice.createWindowDevice(width, height); + String name = isFastRDevice ? "awt" : "X11cairo"; + GridContext.getContext().setCurrentDevice(name, device); + return RNull.instance; + } + + private Object openImageDevice(String name, int width, int height) { + String formatName = name.substring(0, name.indexOf("::")); + String filename = name.substring(name.lastIndexOf(':') + 1); + try { + BufferedImageDevice device = BufferedImageDevice.open(filename, formatName, width, height); + GridContext.getContext().setCurrentDevice(formatName, device); + } catch (NotSupportedImageFormatException e) { + throw error(Message.GENERIC, String.format("Format '%s' is not supported.", formatName)); + } + return RNull.instance; + } + + private static int getIntOrDefault(RArgsValuesAndNames args, int index, int defaultValue) { + if (index >= args.getLength()) { + return defaultValue; + } + int value = RRuntime.asInteger(args.getArgument(index)); + if (RRuntime.isNA(value)) { + return defaultValue; + } + return value; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R new file mode 100644 index 0000000000000000000000000000000000000000..aad9c69ae671c971c18b81e89920be6f54cc66b5 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R @@ -0,0 +1,54 @@ +# 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. + +eval(expression({ + # This should be preffered way of starting the FastR java device. + # For compatibility reasons, both X11 and awt end up calling C_X11. + # In the future, this function may support extra parameters like a + # reference to java 2D graphics object, which will be used for the drawing. + awt <- function(width = NULL, height = NULL, graphicsObj = NULL) { + .External2(grDevices:::C_X11, ".FASTR.AWT", width, height, graphicsObj) + } + # Allows to get the SVG code from SVG device, it also closes the device, + # but the contents are not saved to the given file. + svg.off <- function(which = dev.cur()) { + if (which == 1) { + stop("cannot shut down device 1 (the null device)") + } + .External(C_devoff, as.integer(-which)) + } + # GnuR version only works with "X11cairo" device. Our version of savePlot + # works with "awt" device and "X11cairo", which is for us only alias for + # "awt". Moreover, we only support formats that awt supports. + savePlot <- function (filename = paste("Rplot", type, sep = "."), type = c("png", "jpeg", "bmp"), device = dev.cur()) { + type <- match.arg(type) + devlist <- dev.list() + devcur <- match(device, devlist, NA) + if (is.na(devcur)) { + stop("no such device") + } + devname <- names(devlist)[devcur] + if (devname != "X11cairo" && devname != "awt") { + stop("can only copy from 'X11(type=\"*cairo\")' or 'awt' devices") + } + invisible(.External2(C_savePlot, filename, type, device)) + } +}), asNamespace("grDevices")) \ No newline at end of file diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/SavePlot.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/SavePlot.java new file mode 100644 index 0000000000000000000000000000000000000000..c42a0e33b9b96c8116cc6439102d52553c929a47 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/SavePlot.java @@ -0,0 +1,62 @@ +/* + * 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.grDevices; + +import java.io.IOException; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.library.fastrGrid.GridContext; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.library.fastrGrid.device.ImageSaver; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.data.RNull; + +public abstract class SavePlot extends RExternalBuiltinNode.Arg3 { + static { + Casts casts = new Casts(SavePlot.class); + casts.arg(0).asStringVector().findFirst(); + casts.arg(1).asStringVector().findFirst(); + } + + public static SavePlot create() { + return SavePlotNodeGen.create(); + } + + @Specialization + @TruffleBoundary + Object savePlot(String filename, String type) { + GridDevice device = GridContext.getContext().getCurrentDevice(); + if (!(device instanceof ImageSaver)) { + throw error(Message.GENERIC, "Current device does not support plot saving. " + + "Note that FastR savePlot function ignores the device argument and always uses the current device."); + } + try { + ((ImageSaver) device).save(filename, type); + } catch (IOException e) { + throw error(Message.GENERIC, "I/O error occured when saving the image."); + } + return RNull.instance; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/package-info.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..f8363aacb3318093101e3a1d9ea3b3e1509a9a5e --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/package-info.java @@ -0,0 +1,31 @@ +/* + * 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. + */ +/** + * Compatibility layer for grDevices packages. + * + * With FastR grid we use {@link com.oracle.truffle.r.library.fastrGrid.device.GridDevice} instead + * of the abstraction used by GnuR. This is compatibility layer that provides implementation of some + * of the externals that manipulate the device and forwards them to corresponding methods on FastR + * grid side. + */ +package com.oracle.truffle.r.library.fastrGrid.grDevices; diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java new file mode 100644 index 0000000000000000000000000000000000000000..39cca90ea1e04c78909fae9683842a6d8f4268cb --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java @@ -0,0 +1,75 @@ +/* + * 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.graphics; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.r.library.fastrGrid.GridContext; +import com.oracle.truffle.r.library.fastrGrid.device.GridDevice; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +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.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RList; + +public final class CPar extends RExternalBuiltinNode { + static { + Casts.noCasts(CPar.class); + } + + @Override + @TruffleBoundary + protected Object call(RArgsValuesAndNames args) { + if (args.getSignature().getNonNullCount() > 0) { + throw error(Message.GENERIC, "Using par for setting device parameters is not supported in FastR grid emulation mode."); + } + + GridDevice device = GridContext.getContext().getCurrentDevice(); + Object[] names = args.getArguments(); + // unwrap list if it is the first argument + if (names.length == 1) { + Object first = args.getArgument(0); + if (first instanceof RList) { + names = ((RList) first).getDataWithoutCopying(); + } + } + + Object[] result = new Object[names.length]; + String[] resultNames = new String[names.length]; + for (int i = 0; i < names.length; i++) { + resultNames[i] = RRuntime.asString(names[i]); + result[i] = getParam(resultNames[i], device); + } + return RDataFactory.createList(result, RDataFactory.createStringVector(resultNames, RDataFactory.COMPLETE_VECTOR)); + } + + private Object getParam(String name, GridDevice device) { + switch (name) { + case "din": + return RDataFactory.createDoubleVector(new double[]{device.getWidth(), device.getHeight()}, RDataFactory.COMPLETE_VECTOR); + default: + throw RError.nyi(RError.NO_CALLER, "C_Par parameter '" + name + "'"); + } + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..f99012e978ce97b5acaeadaa66f323021627937c --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java @@ -0,0 +1,133 @@ +/* + * 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) 1995, 1996 Robert Gentleman and Ross Ihaka + * Copyright (C) 1998 Ross Ihaka + * Copyright (c) 1998--2014, The R Core Team + * Copyright (c) 2002--2010, The R Foundation + * Copyright (C) 2005--2006, Morten Welinder + * Copyright (c) 2014, 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.fastrGrid.graphics; + +import com.oracle.truffle.r.library.fastrGrid.FastRGridExternalLookup; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.ROptions; +import com.oracle.truffle.r.runtime.ROptions.OptionsException; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RPairList; +import com.oracle.truffle.r.runtime.env.REnvironment; + +/** + * Initialization of graphics package emulation for the purposes of FastR grid package + * implementation. + * + * FastR exposes two devices: the null device and 'awt' device, and adds function 'awt' to the + * grDevices package. The 'awt' function ends up calling 'C_X11' (the same as the 'X11' function + * from grDevices), we capture that call in {@link FastRGridExternalLookup} and replace it with our + * own logic. This way we also "implement" 'X11' device with java awt should anyone try to activate + * it. + * + * Moreover, we change the value of option "device" to our "awt" function so that when e.g. lattice + * tries to open the default device it uses 'awt'. If the future this should be either 'awt' for + * interactive sessions, or some image format device for batch sessions. We should also honor the + * R_INTERACTIVE_DEVICE and R_DEFAULT_DEVICE environment variables. + * + * The responsibility of this class if to provide convenient access to those R-level variables. The + * actual devices instances are maintained in + * {@link com.oracle.truffle.r.library.fastrGrid.GridContext} since we only have grid devices and no + * generic graphics devices. + */ +public final class RGridGraphicsAdapter { + private static final String DEFAULT_DEVICE_OPTION = "device"; + private static final String NULL_DEVICE = "null device"; + /** + * The graphics devices system maintains two variables .Device and .Devices in the base + * environment both are always set: .Devices gives a list of character vectors of the names of + * open devices, .Device is the element corresponding to the currently active device. The null + * device will always be open. + */ + private static final String DOT_DEVICE = ".Device"; + private static final String DOT_DEVICES = ".Devices"; + + private RGridGraphicsAdapter() { + // only static members + } + + public static void initialize() { + addDevice(NULL_DEVICE); + setCurrentDevice(NULL_DEVICE); + ROptions.ContextStateImpl options = RContext.getInstance().stateROptions; + try { + options.setValue(DEFAULT_DEVICE_OPTION, "awt"); + } catch (OptionsException e) { + RError.warning(RError.NO_CALLER, Message.GENERIC, "FastR could not set the 'device' options to awt."); + } + } + + public static void removeDevice(int index) { + assert index > 0 : "cannot remove null device"; + REnvironment baseEnv = REnvironment.baseEnv(); + RPairList devices = (RPairList) baseEnv.get(DOT_DEVICES); + assert index < devices.getLength() : "wrong index in removeDevice"; + RPairList prev = devices; + for (int i = 0; i < index - 1; ++i) { + prev = (RPairList) prev.cdr(); + } + RPairList toRemove = (RPairList) prev.cdr(); + prev.setCdr(toRemove.cdr()); + setCurrentDevice((String) prev.car()); + } + + public static void setCurrentDevice(String name) { + REnvironment baseEnv = REnvironment.baseEnv(); + assert contains((RPairList) baseEnv.get(DOT_DEVICES), name) : "setCurrentDevice can be invoked only after the device is added with addDevice"; + baseEnv.safePut(DOT_DEVICE, name); + } + + public static void addDevice(String name) { + REnvironment baseEnv = REnvironment.baseEnv(); + baseEnv.safePut(DOT_DEVICE, name); + Object dotDevices = baseEnv.get(DOT_DEVICES); + if (dotDevices instanceof RPairList) { + ((RPairList) dotDevices).appendToEnd(RDataFactory.createPairList(name)); + } else { + baseEnv.safePut(DOT_DEVICES, RDataFactory.createPairList(name)); + } + } + + public static String getDefaultDevice() { + ROptions.ContextStateImpl options = RContext.getInstance().stateROptions; + String defaultDev = RRuntime.asString(options.getValue(DEFAULT_DEVICE_OPTION)); + if (RRuntime.isNA(defaultDev)) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "FastR does only supports character value as the default 'device' option"); + } + return defaultDev; + } + + public static int getDevicesCount() { + Object dotDevices = REnvironment.baseEnv().get(DOT_DEVICES); + return dotDevices instanceof RPairList ? ((RPairList) dotDevices).getLength() : 0; + } + + public static String getDeviceName(int index) { + RPairList dotDevices = (RPairList) REnvironment.baseEnv().get(DOT_DEVICES); + return RRuntime.asString(dotDevices.getDataAtAsObject(index)); + } + + private static boolean contains(RPairList devices, String name) { + for (RPairList dev : devices) { + if (dev.car().equals(name)) { + return true; + } + } + return false; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/package-info.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..4e19a7b99e7e0e5242d1b4783c80c3083f754354 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/package-info.java @@ -0,0 +1,29 @@ +/* + * 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. + */ +/** + * Compatibility layer for graphics package. + * + * Some R code that uses mainly grid for drawing resorts to several graphics package functions, + * especially in order to control or query information about device(s). + */ +package com.oracle.truffle.r.library.fastrGrid.graphics; diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java deleted file mode 100644 index 539994d1f72cc6389624c2d03b341aaf0d206a1f..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2017, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.grDevices; - -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyStringVector; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; -import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder; - -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.r.library.grDevices.DevicesCCallsFactory.C_DevOffNodeGen; -import com.oracle.truffle.r.library.grDevices.pdf.PdfGraphicsDevice; -import com.oracle.truffle.r.library.graphics.core.GraphicsEngineImpl; -import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; -import com.oracle.truffle.r.nodes.unary.CastNode; -import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; - -public class DevicesCCalls { - public abstract static class C_DevOff extends RExternalBuiltinNode.Arg1 { - public static C_DevOff create() { - return C_DevOffNodeGen.create(); - } - - static { - Casts casts = new Casts(C_DevOff.class); - casts.arg(0).asIntegerVector().findFirst(); - } - - @Specialization - public Object doCall(int deviceIndex) { - GraphicsEngineImpl.getInstance().killGraphicsDeviceByIndex(deviceIndex); - return RNull.instance; - } - } - - public static final class C_DevCur extends RExternalBuiltinNode.Arg0 { - - @Override - @TruffleBoundary - public Object execute() { - return GraphicsEngineImpl.getInstance().getCurrentGraphicsDeviceIndex(); - } - } - - public static final class C_PDF extends RExternalBuiltinNode { - - @Child private CastNode extractFontsNode; - @Child private CastNode asStringNode; - @Child private CastNode asDoubleNode; - @Child private CastNode asLogicalNode; - @Child private CastNode asIntNode; - - static { - Casts.noCasts(C_PDF.class); - } - - public C_PDF() { - asStringNode = newCastBuilder().asStringVector().findFirst().buildCastNode(); - asDoubleNode = newCastBuilder().asDoubleVector().findFirst().buildCastNode(); - asLogicalNode = newCastBuilder().asLogicalVector().findFirst().buildCastNode(); - asIntNode = newCastBuilder().asIntegerVector().findFirst().buildCastNode(); - extractFontsNode = newCastBuilder().mapNull(emptyStringVector()).mustBe(stringValue()).asStringVector().buildCastNode(); - } - - @SuppressWarnings("unused") - @Override - @TruffleBoundary - public Object call(RArgsValuesAndNames args) { - new PdfGraphicsDevice(extractParametersFrom(args)); - // todo implement devices addition - return RNull.instance; - } - - private PdfGraphicsDevice.Parameters extractParametersFrom(RArgsValuesAndNames args) { - PdfGraphicsDevice.Parameters result = new PdfGraphicsDevice.Parameters(); - result.filePath = asString(args.getArgument(0)); - result.paperSize = asString(args.getArgument(1)); - result.fontFamily = asString(args.getArgument(2)); - result.encoding = asString(args.getArgument(3)); - result.bg = asString(args.getArgument(4)); - result.fg = asString(args.getArgument(5)); - result.width = asDouble(castVector(args.getArgument(6))); - result.height = asDouble(castVector(args.getArgument(7))); - result.pointSize = asDouble(castVector(args.getArgument(8))); - result.oneFile = asLogical(castVector(args.getArgument(9))); - result.pageCenter = asLogical(castVector(args.getArgument(10))); - result.title = asString(args.getArgument(11)); - result.fonts = extractFontsFrom(args.getArgument(12)); - - result.majorVersion = asInt(castVector(args.getArgument(13))); - result.minorVersion = asInt(castVector(args.getArgument(14))); - result.colormodel = asString(args.getArgument(15)); - result.useDingbats = asLogical(castVector(args.getArgument(16))); - result.useKerning = asLogical(castVector(args.getArgument(17))); - result.fillOddEven = asLogical(castVector(args.getArgument(18))); - result.compress = asLogical(castVector(args.getArgument(19))); - return result; - } - - private String asString(Object value) { - return (String) asStringNode.execute(value); - } - - private int asInt(Object value) { - return (Integer) asIntNode.execute(value); - } - - private double asDouble(Object value) { - return (Double) asDoubleNode.execute(value); - } - - private byte asLogical(Object value) { - return (Byte) asLogicalNode.execute(value); - } - - private String[] extractFontsFrom(Object inputArgument) { - return ((RAbstractStringVector) extractFontsNode.execute(inputArgument)).materialize().getDataCopy(); - } - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/NullGraphicsDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/NullGraphicsDevice.java deleted file mode 100644 index 0ec439c90287e887c4869771a65ef7bad33ac17f..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/NullGraphicsDevice.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.grDevices; - -import com.oracle.truffle.r.library.graphics.core.DrawingParameters; -import com.oracle.truffle.r.library.graphics.core.GraphicsDevice; -import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates; - -public final class NullGraphicsDevice implements GraphicsDevice { - private static final NullGraphicsDevice instance = new NullGraphicsDevice(); - - public static NullGraphicsDevice getInstance() { - return instance; - } - - @Override - public void deactivate() { - throw createExceptionForMethod("deactivate"); - } - - @Override - public void activate() { - throw createExceptionForMethod("activate"); - } - - @Override - public void close() { - throw createExceptionForMethod("close"); - } - - @Override - public DrawingParameters getDrawingParameters() { - throw createExceptionForMethod("getDrawingParameters"); - } - - @Override - public void setMode(Mode newMode) { - throw createExceptionForMethod("setMode"); - } - - @Override - public Mode getMode() { - throw createExceptionForMethod("getMode"); - } - - @Override - public void setClipRect(double x1, double y1, double x2, double y2) { - throw createExceptionForMethod("setClipRect"); - } - - @Override - public void drawPolyline(Coordinates coordinates, DrawingParameters drawingParameters) { - throw createExceptionForMethod("drawPolyline"); - } - - private static RuntimeException createExceptionForMethod(String methodName) { - return new IllegalStateException("Call to " + methodName + " of Null-device"); - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/fastrgd/FastRGraphicsDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/fastrgd/FastRGraphicsDevice.java deleted file mode 100644 index ca8976b7907f25bacb5b9ac22c8ee65720fc7f19..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/fastrgd/FastRGraphicsDevice.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2016, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.grDevices.fastrgd; - -import static com.oracle.truffle.r.library.graphics.core.geometry.AxisDirection.EAST; -import static com.oracle.truffle.r.library.graphics.core.geometry.AxisDirection.NORTH; - -import java.util.Arrays; -import java.util.function.Function; - -import com.oracle.truffle.r.library.graphics.FastRFrame; -import com.oracle.truffle.r.library.graphics.core.DrawingParameters; -import com.oracle.truffle.r.library.graphics.core.GraphicsDevice; -import com.oracle.truffle.r.library.graphics.core.drawables.DrawableObject; -import com.oracle.truffle.r.library.graphics.core.drawables.PolylineDrawableObject; -import com.oracle.truffle.r.library.graphics.core.drawables.StringDrawableObject; -import com.oracle.truffle.r.library.graphics.core.geometry.Axis; -import com.oracle.truffle.r.library.graphics.core.geometry.CoordinateSystem; -import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates; -import com.oracle.truffle.r.library.graphics.core.geometry.CoordinatesFactory; -import com.oracle.truffle.r.library.graphics.core.geometry.DoubleCoordinates; - -/** - * Default interactive FastR graphics device. - */ -public class FastRGraphicsDevice implements GraphicsDevice { - private static final double GNUR_DEFAULT_MAX_X = 1; - private static final Axis GNUR_DEFAULT_X_AXIS = new Axis(0, GNUR_DEFAULT_MAX_X, EAST); - private static final Axis GNUR_DEFAULT_Y_AXIS = new Axis(0, 1, NORTH); - private static final double MARGIN = GNUR_DEFAULT_MAX_X * 0.1; // the margin for each side of - // 10% of a screen - // compress resulting image to have a small margin on all sides - private static final double COMPRESS_RATION = 1. - MARGIN * 1.8; - - private Mode mode = Mode.GRAPHICS_OFF; - private FastRFrame fastRFrame; - private CoordinateSystem currentCoordinateSystem = new CoordinateSystem(GNUR_DEFAULT_X_AXIS, GNUR_DEFAULT_Y_AXIS); - - @Override - public void deactivate() { - // todo impl - } - - @Override - public void activate() { - // todo impl - } - - @Override - public void close() { - // todo impl - } - - @Override - public DrawingParameters getDrawingParameters() { - return null; - } - - @Override - public void setMode(Mode newMode) { - mode = newMode; - } - - @Override - public Mode getMode() { - return mode; - } - - @Override - public void setClipRect(double x1, double y1, double x2, double y2) { - // todo impl - } - - @Override - public void drawPolyline(Coordinates coordinates, DrawingParameters drawingParameters) { - // todo continue from GEPolyline() of engine.c - Coordinates convertedCoords = CoordinatesFactory.withRatioAndShift(coordinates, COMPRESS_RATION, MARGIN); - addDrawableObject(new PolylineDrawableObject(currentCoordinateSystem, convertedCoords)); - drawBounds(); - drawXYLabelsFor(coordinates); - } - - private void drawBounds() { - // x,y in range [0,1] - double[] boundsXYPairs = {0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0}; - Coordinates bounds = CoordinatesFactory.createByXYPairs(boundsXYPairs); - Coordinates compressedBounds = CoordinatesFactory.withRatioAndShift(bounds, COMPRESS_RATION, MARGIN); - addDrawableObject(new PolylineDrawableObject(currentCoordinateSystem, compressedBounds)); - } - - private void drawXYLabelsFor(Coordinates coordinates) { - drawLabelsForCoordinates(coordinates.getXCoordinatesAsDoubles(), MARGIN, 0.01, // just small - // shift - d -> CoordinatesFactory.createWithSameY(d, 0)); - drawLabelsForCoordinates(coordinates.getYCoordinatesAsDoubles(), 0, MARGIN, d -> CoordinatesFactory.createWithSameX(0, d)); - } - - private void drawLabelsForCoordinates(double[] coordinates, double xShift, double yShift, Function<double[], DoubleCoordinates> xYConverter) { - int length = coordinates.length; - double[] sortedCoords = new double[length]; - // copy to avoid side-effects on a caller side - System.arraycopy(coordinates, 0, sortedCoords, 0, length); - Arrays.sort(sortedCoords); - String[] labels = composeLabelsFor(sortedCoords); - DoubleCoordinates xYCoords = xYConverter.apply(sortedCoords); - Coordinates shiftedCoords = CoordinatesFactory.withRatioAndShift(xYCoords, COMPRESS_RATION, xShift, yShift); - addDrawableObject(new StringDrawableObject(currentCoordinateSystem, shiftedCoords, labels)); - } - - private static String[] composeLabelsFor(double[] doubles) { - return Arrays.stream(doubles).mapToObj(String::valueOf).toArray(String[]::new); - } - - private FastRFrame getFastRFrame() { - if (fastRFrame == null || !fastRFrame.isVisible()) { - fastRFrame = new FastRFrame(); - fastRFrame.setVisible(true); - } - return fastRFrame; - } - - private void addDrawableObject(DrawableObject drawableObject) { - getFastRFrame().getFastRComponent().addDrawableObject(drawableObject); - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/pdf/PdfGraphicsDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/pdf/PdfGraphicsDevice.java deleted file mode 100644 index 9b7302823dec1669faa446b3a71a2723d628cbe4..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/pdf/PdfGraphicsDevice.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.grDevices.pdf; - -import com.oracle.truffle.r.library.graphics.core.DrawingParameters; -import com.oracle.truffle.r.library.graphics.core.GraphicsDevice; -import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates; -import com.oracle.truffle.r.runtime.RRuntime; - -public class PdfGraphicsDevice implements GraphicsDevice { - @SuppressWarnings("unused") private final Parameters deviceParameters; - - public PdfGraphicsDevice(Parameters deviceParameters) { - this.deviceParameters = deviceParameters; - } - - @Override - public void deactivate() { - - } - - @Override - public void activate() { - - } - - @Override - public void close() { - - } - - @Override - public DrawingParameters getDrawingParameters() { - return null; - } - - @Override - public void setMode(Mode newMode) { - - } - - @Override - public Mode getMode() { - return null; - } - - @Override - public void setClipRect(double x1, double y1, double x2, double y2) { - - } - - @Override - public void drawPolyline(Coordinates coordinates, DrawingParameters drawingParameters) { - - } - - public static class Parameters { - public String filePath; - public String paperSize = "special"; - public String fontFamily = "Helvetica"; - public String encoding = "default"; - public String bg = "transparent"; - public String fg = "black"; - public double width = 7.; - public double height = 7.; - public double pointSize = 12.; - public byte oneFile = RRuntime.LOGICAL_TRUE; - public byte pageCenter = RRuntime.LOGICAL_TRUE; - public String title = "R Graphics Output"; - public String[] fonts; - public int majorVersion = 1; - public int minorVersion = 4; - public String colormodel = "srgb"; - public byte useDingbats = RRuntime.LOGICAL_TRUE; - public byte useKerning = RRuntime.LOGICAL_TRUE; - public byte fillOddEven = RRuntime.LOGICAL_FALSE; - public byte compress = RRuntime.LOGICAL_TRUE; - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/BaseGraphicsSystem.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/BaseGraphicsSystem.java deleted file mode 100644 index 77d572f534a7ef158c16829b4d7fa953fbaca328..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/BaseGraphicsSystem.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics; - -import com.oracle.truffle.r.library.graphics.core.AbstractGraphicsSystem; - -/** - * Denotes to the 'base' in GNUR terms graphics system. - */ -public class BaseGraphicsSystem extends AbstractGraphicsSystem { - private final GraphicsEventsListener graphicsEventsListener = (graphicsEvent, graphicsDevice) -> { - }; - - @Override - public GraphicsEventsListener getGraphicsEventsListener() { - return graphicsEventsListener; - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRComponent.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRComponent.java deleted file mode 100644 index 5f395fecd1afe721a1f2f435c417169f7b88fcd0..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRComponent.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2016, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics; - -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import javax.swing.JComponent; - -import com.oracle.truffle.r.library.graphics.core.drawables.DrawableObject; -import com.oracle.truffle.r.library.graphics.core.geometry.CoordinateSystem; - -public class FastRComponent extends JComponent { - - private static final long serialVersionUID = 1L; - - private final List<DrawableObject> displayList = Collections.synchronizedList(new ArrayList<>()); - - private boolean shouldDraw; - private CoordinateSystem coordinateSystem; - - /** - * Note! Called from ED thread. - */ - @Override - public void doLayout() { - super.doLayout(); - Dimension size = getSize(); - coordinateSystem = new CoordinateSystem(0, size.getWidth(), 0, size.getHeight()); - shouldDraw = true; - recalculateDisplayList(); - } - - private void recalculateDisplayList() { - synchronized (displayList) { - displayList.stream().forEach(drawableObject -> drawableObject.recalculateForDrawingIn(coordinateSystem)); - } - } - - /** - * Note! Called from ED thread. - */ - @Override - protected void paintComponent(Graphics g) { - super.paintComponent(g); - Graphics2D g2 = (Graphics2D) g; - if (shouldDraw) { - drawDisplayListOn(g2); - } - } - - private void drawDisplayListOn(Graphics2D g2) { - synchronized (displayList) { - displayList.stream().forEach(drawableObject -> drawableObject.drawOn(g2)); - } - } - - public void addDrawableObject(DrawableObject drawableObject) { - synchronized (displayList) { - displayList.add(drawableObject); - } - shouldDraw = true; - if (coordinateSystem != null) { - drawableObject.recalculateForDrawingIn(coordinateSystem); - repaint(); - } - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRFrame.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRFrame.java deleted file mode 100644 index 9f1463e8549ecc02f5eca556a94f7e22426d590b..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRFrame.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2014, 2016, 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.graphics; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.HeadlessException; -import java.awt.Toolkit; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; - -import javax.swing.JFrame; - -public class FastRFrame extends JFrame { - - private static final long serialVersionUID = 1L; - - private final Dimension framePreferredSize = new Dimension(500, 500); - private final FastRComponent fastRComponent = new FastRComponent(); - - public FastRFrame() throws HeadlessException { - super("FastR"); - addCloseListener(); - createUI(); - center(); - } - - private void createUI() { - setLayout(new BorderLayout()); - setSize(framePreferredSize); - add(fastRComponent, BorderLayout.CENTER); - fastRComponent.setPreferredSize(getSize()); - } - - private void addCloseListener() { - addWindowFocusListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - dispose(); - } - }); - } - - private void center() { - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - Dimension frameSize = getSize(); - int x = (screenSize.width - frameSize.width) / 2; - int y = (screenSize.height - frameSize.height) / 2; - setLocation(x, y); - } - - public FastRComponent getFastRComponent() { - return fastRComponent; - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java deleted file mode 100644 index 695ba86dbbfa3af1761cecfaba525de6ed53f736..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2017, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics; - -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size; -import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder; - -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.r.library.graphics.core.DrawingParameters; -import com.oracle.truffle.r.library.graphics.core.GraphicsDevice; -import com.oracle.truffle.r.library.graphics.core.GraphicsEngine; -import com.oracle.truffle.r.library.graphics.core.GraphicsEngineImpl; -import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates; -import com.oracle.truffle.r.library.graphics.core.geometry.CoordinatesFactory; -import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; -import com.oracle.truffle.r.nodes.unary.CastNode; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RDoubleVector; -import com.oracle.truffle.r.runtime.data.RNull; - -public class GraphicsCCalls { - public static final class C_PlotXY extends RExternalBuiltinNode { - @Child private CastNode castXYNode; - - static { - Casts.noCasts(C_PlotXY.class); - } - - public C_PlotXY() { - castXYNode = newCastBuilder().mustBe(doubleValue().and(size(2))).asDoubleVector().buildCastNode(); - } - - @Override - @TruffleBoundary - public RNull call(RArgsValuesAndNames args) { - RDoubleVector xyVector = (RDoubleVector) castXYNode.execute(args.getArgument(0)); - getGraphicsEngine().setCurrentGraphicsDeviceMode(GraphicsDevice.Mode.GRAPHICS_ON); - drawWithLines(xyVector); - return RNull.instance; - } - - private static void drawWithLines(RDoubleVector xyVector) { - // todo implement coordinate systems units conversion like in GConvert (graphics.c) - setClipRect(); - DrawingParameters adoptedParameters = adoptCurrentDeviceDrawingParameters(); - Coordinates coordinates = CoordinatesFactory.createByXYVector(xyVector); - getGraphicsEngine().drawPolyline(coordinates, adoptedParameters); - } - - private static DrawingParameters adoptCurrentDeviceDrawingParameters() { - // todo Now adoption as for today. Transcribe from gcontextFromGM() (graphics.c) - return getCurrentGraphicsDevice().getDrawingParameters(); - } - - private static void setClipRect() { - // todo Transcrive from Gclip() (graphics.c) - getGraphicsEngine().setCurrentGraphicsDeviceClipRect(0, 0, 0, 0); - } - - private static GraphicsDevice getCurrentGraphicsDevice() { - return getGraphicsEngine().getCurrentGraphicsDevice(); - } - - private static GraphicsEngine getGraphicsEngine() { - return GraphicsEngineImpl.getInstance(); - } - } - - public static final class C_Par extends RExternalBuiltinNode { - - static { - Casts.noCasts(C_Par.class); - } - - @Override - @TruffleBoundary - public Object call(RArgsValuesAndNames args) { - // pch - return RDataFactory.createIntVectorFromScalar(1); - } - } - - @SuppressWarnings("unused") - public static final class C_mtext extends RExternalBuiltinNode { - private Object text; - private double side = 3.; - private double line = 0.; - private boolean outer = true; - private double adj = RRuntime.DOUBLE_NA; - private double at = RRuntime.DOUBLE_NA; - private double padj = RRuntime.DOUBLE_NA; - private double cex = RRuntime.DOUBLE_NA; - private double col = RRuntime.DOUBLE_NA; - private double font = RRuntime.DOUBLE_NA; - @Child private CastNode firstDoubleCast; - - static { - Casts.noCasts(C_mtext.class); - } - - public C_mtext() { - firstDoubleCast = newCastBuilder().asDoubleVector().findFirst().buildCastNode(); - } - - @Override - @TruffleBoundary - public Object call(RArgsValuesAndNames args) { - extractArgumentsFrom(args); - return RNull.instance; - } - - private void extractArgumentsFrom(RArgsValuesAndNames args) { - // text = args.getArgument(0); // postpone for now - side = extractFirstDoubleValueFrom(args.getArgument(1)); - line = extractFirstDoubleValueFrom(args.getArgument(2)); - // outer = extractFirstDoubleValueFrom(args.getArgument(3)); - at = extractFirstDoubleValueFrom(args.getArgument(4)); - adj = extractFirstDoubleValueFrom(args.getArgument(5)); - padj = extractFirstDoubleValueFrom(args.getArgument(6)); - cex = extractFirstDoubleValueFrom(args.getArgument(7)); - // col = extractFirstDoubleValueFrom(args.getArgument(8)); - font = extractFirstDoubleValueFrom(args.getArgument(9)); - } - - private double extractFirstDoubleValueFrom(Object arg) { - return (Double) firstDoubleCast.execute(arg); - } - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java index 11c4a71ce6b38c8afb385a9a5be2670ce5a16a14..657822c2172dfb24bbcb85fb8878d78a248b957b 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java @@ -16,70 +16,30 @@ package com.oracle.truffle.r.library.graphics; import java.util.concurrent.atomic.AtomicBoolean; -import com.oracle.truffle.r.library.graphics.core.GraphicsEngine; -import com.oracle.truffle.r.library.graphics.core.GraphicsEngineImpl; +import com.oracle.truffle.r.library.fastrGrid.graphics.RGridGraphicsAdapter; import com.oracle.truffle.r.runtime.FastROptions; -import com.oracle.truffle.r.runtime.context.ConsoleHandler; -import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RPairList; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.env.REnvironment; -import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.CallRFFI; +import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; /** - * A placeholder to keep {@code REngine} limited to calling the {@link #initialize} method. Two - * possible implementations are available: - * <ul> - * <li>Native graphics from GnuR</li> - * <li>Internal (Java) graphics, very incomplete implementation</li> - * </ul> - * The default is native graphics, selected by a startup option. Graphics is not virtualized, so - * multiple contexts all share the same underlying implementation which is initialized exactly once. - * + * A placeholder to keep {@code REngine} limited to calling the {@link #initialize} method. The code + * in R has a hard-coded invocation to InitGraphics in it. This initialization either invokes it + * too, or it runs a Java version of it if the internal grid package implementation is to be used. */ public class RGraphics { - private static final RStringVector NULL_DEVICE = RDataFactory.createStringVectorFromScalar("null device"); - /** - * The graphics devices system maintains two variables .Device and .Devices in the base - * environment both are always set: .Devices gives a list of character vectors of the names of - * open devices, .Device is the element corresponding to the currently active device. The null - * device will always be open. - */ - private static final String DOT_DEVICE = ".Device"; - private static final String DOT_DEVICES = ".Devices"; private static final AtomicBoolean initialized = new AtomicBoolean(); public static void initialize() { if (initialized.compareAndSet(false, true)) { - if (FastROptions.UseInternalGraphics.getBooleanValue()) { - REnvironment baseEnv = REnvironment.baseEnv(); - baseEnv.safePut(DOT_DEVICE, NULL_DEVICE); - RPairList devices = RDataFactory.createPairList(NULL_DEVICE); - baseEnv.safePut(DOT_DEVICES, devices); - registerBaseGraphicsSystem(); - } else { - DLL.DLLInfo dllInfo = DLL.findLibrary("graphics"); + if (FastROptions.UseInternalGridGraphics.getBooleanValue()) { + RGridGraphicsAdapter.initialize(); + } else if (FastROptions.LoadPackagesNativeCode.getBooleanValue()) { + DLL.DLLInfo dllInfo = DLL.findLibraryContainingSymbol("InitGraphics"); DLL.SymbolHandle symbolHandle = DLL.findSymbol("InitGraphics", dllInfo); assert symbolHandle != DLL.SYMBOL_NOT_FOUND; CallRFFI.InvokeVoidCallRootNode.create().getCallTarget().call(new NativeCallInfo("InitGraphics", symbolHandle, dllInfo), new Object[0]); } } } - - private static void registerBaseGraphicsSystem() { - try { - getGraphicsEngine().registerGraphicsSystem(new BaseGraphicsSystem()); - } catch (Exception e) { - e.printStackTrace(); - ConsoleHandler consoleHandler = RContext.getInstance().getConsoleHandler(); - consoleHandler.println("Unable to register base graphics system"); - } - } - - private static GraphicsEngine getGraphicsEngine() { - return GraphicsEngineImpl.getInstance(); - } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/AbstractGraphicsSystem.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/AbstractGraphicsSystem.java deleted file mode 100644 index b401568ffa06f437c046cded9d3cbc363ed84de2..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/AbstractGraphicsSystem.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics.core; - -public abstract class AbstractGraphicsSystem implements GraphicsSystem { - private final GraphicsSystemParameters graphicsSystemParameters = new GraphicsSystemParameters(); - private int id; - - protected GraphicsSystemParameters getGraphicsSystemParameters() { - return graphicsSystemParameters; - } - - @Override - public void setId(int id) { - this.id = id; - } - - @Override - public int getId() { - return id; - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/DrawingParameters.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/DrawingParameters.java deleted file mode 100644 index 69a1d7075210e9646fe22300db31d18f1678b7ab..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/DrawingParameters.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics.core; - -// todo implement GEContext data structure (GraphicsEngine.h) -public final class DrawingParameters { -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsDevice.java deleted file mode 100644 index 91e07584d7ea7e37edfe40fa83075849642823cb..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsDevice.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2016, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics.core; - -import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates; - -public interface GraphicsDevice { - void deactivate(); - - void activate(); - - void close(); - - DrawingParameters getDrawingParameters(); - - void setMode(Mode newMode); - - Mode getMode(); - - void setClipRect(double x1, double y1, double x2, double y2); - - void drawPolyline(Coordinates coordinates, DrawingParameters drawingParameters); - - enum Mode { - GRAPHICS_ON, // allow graphics output - GRAPHICS_OFF // disable graphics output - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngine.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngine.java deleted file mode 100644 index 57a70b07e2e802fa89ba89a5af7e0702613c7b31..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngine.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics.core; - -import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates; - -public interface GraphicsEngine { - void registerGraphicsSystem(GraphicsSystem newGraphicsSystem) throws Exception; - - void unRegisterGraphicsSystem(GraphicsSystem graphicsSystem); - - void registerGraphicsDevice(GraphicsDevice newGraphicsDevice) throws Exception; - - void unRegisterGraphicsDevice(GraphicsDevice deviceToUnregister); - - int getGraphicsDevicesAmount(); - - /** - * @return true if there is only Null graphics device registered - */ - boolean noGraphicsDevices(); - - /** - * Tries to install one if there is no current device. - * - * @return current {@link GraphicsDevice} - */ - GraphicsDevice getCurrentGraphicsDevice(); - - /** - * @return {@link com.oracle.truffle.r.library.grDevices.NullGraphicsDevice} if unable to find - * other - */ - GraphicsDevice getGraphicsDeviceNextTo(GraphicsDevice graphicsDevice); - - /** - * @return {@link com.oracle.truffle.r.library.grDevices.NullGraphicsDevice} if unable to find - * other - */ - GraphicsDevice getGraphicsDevicePrevTo(GraphicsDevice graphicsDevice); - - void setCurrentGraphicsDeviceMode(GraphicsDevice.Mode mode); - - void setCurrentGraphicsDeviceClipRect(double x1, double y1, double x2, double y2); - - void drawPolyline(Coordinates coordinates, DrawingParameters drawingParameters); - - void killGraphicsDeviceByIndex(int graphicsDeviceIndex); - - int getCurrentGraphicsDeviceIndex(); -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngineImpl.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngineImpl.java deleted file mode 100644 index 5efaee6e6765608e465e3d67d2b606db4dec8c0a..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngineImpl.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2016, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics.core; - -import static com.oracle.truffle.r.library.graphics.core.GraphicsEvent.GE_FINAL_STATE; -import static com.oracle.truffle.r.library.graphics.core.GraphicsEvent.GE_INIT_STATE; - -import com.oracle.truffle.r.library.grDevices.NullGraphicsDevice; -import com.oracle.truffle.r.library.grDevices.fastrgd.FastRGraphicsDevice; -import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates; -import com.oracle.truffle.r.runtime.Utils; - -// todo implement 'active' devices array from devices.c -public final class GraphicsEngineImpl implements GraphicsEngine { - // GNUR: GraphicsEngine.h (original value: 24) - private static final int MAX_GRAPHICS_SYSTEMS_AMOUNT = 48; - private static final int MAX_GRAPHICS_DEVICES_AMOUNT = 64; - private static final int NULL_GRAPHICS_DEVICE_INDEX = 0; - private static final int LAST_GRAPHICS_DEVICE_INDEX = MAX_GRAPHICS_DEVICES_AMOUNT - 1; - private static final int NOT_FOUND = -1; - private static final GraphicsEngine instance = new GraphicsEngineImpl(); - - /** - * According to GNUR devices.c: 0 - null device, 63 - empty. - */ - private final GraphicsDevice[] graphicsDevices = new GraphicsDevice[MAX_GRAPHICS_DEVICES_AMOUNT]; - private final GraphicsSystem[] graphicsSystems = new AbstractGraphicsSystem[MAX_GRAPHICS_SYSTEMS_AMOUNT]; - - private int graphicsSystemsAmount = 0; - private int devicesAmountWithoutNullDevice = 0; - private CurrentGraphicsDevice currentGraphicsDevice = new CurrentGraphicsDevice(NullGraphicsDevice.getInstance(), NULL_GRAPHICS_DEVICE_INDEX); - - public static GraphicsEngine getInstance() { - return instance; - } - - private GraphicsEngineImpl() { - initNullGraphicsDevice(); - } - - /** - * According to GNUR 0 index is for the Null graphics device. - */ - private void initNullGraphicsDevice() { - graphicsDevices[NULL_GRAPHICS_DEVICE_INDEX] = NullGraphicsDevice.getInstance(); - } - - @Override - public void registerGraphicsSystem(GraphicsSystem newGraphicsSystem) throws Exception { - if (newGraphicsSystem == null) { - throw new NullPointerException("Graphics system to register is null"); - } - int index = findElementIndexInArray(null, graphicsSystems); // find null in the - // graphicsSystems - if (NOT_FOUND == index) { - throw handleErrorAndMakeException("too many graphics systems registered"); - } - newGraphicsSystem.setId(index); - graphicsSystems[index] = newGraphicsSystem; - callListenerForEachDevice(newGraphicsSystem.getGraphicsEventsListener(), GE_INIT_STATE); - graphicsSystemsAmount++; - } - - private void callListenerForEachDevice(AbstractGraphicsSystem.GraphicsEventsListener listener, GraphicsEvent event) { - if (noGraphicsDevices()) { - return; - } - for (int i = NULL_GRAPHICS_DEVICE_INDEX + 1; i < LAST_GRAPHICS_DEVICE_INDEX; i++) { - GraphicsDevice graphicsDevice = graphicsDevices[i]; - if (graphicsDevice != null) { - listener.onEvent(event, graphicsDevice); - } - } - } - - // todo transcribe error(_(msg)) from errors.c - private static Exception handleErrorAndMakeException(String message) { - return new Exception(message); - } - - // todo implement in GNUR way - private static void issueWarning(String warningMessage) { - Utils.warn(warningMessage); - } - - @Override - public void unRegisterGraphicsSystem(GraphicsSystem graphicsSystem) { - int graphicsSystemId = graphicsSystem.getId(); - checkGraphicsSystemIndex(graphicsSystemId); - if (graphicsSystemsAmount == 0) { - issueWarning("no graphics system to unregister"); - return; - } - callListenerForEachDevice(graphicsSystem.getGraphicsEventsListener(), GE_FINAL_STATE); - graphicsSystems[graphicsSystemId] = null; - graphicsSystemsAmount--; - } - - private void checkGraphicsSystemIndex(int graphicsSystemIndex) { - if (graphicsSystemIndex < 0 || graphicsSystemIndex >= graphicsSystems.length) { - throw new IllegalArgumentException("Wrong graphics system index: " + graphicsSystemIndex); - } - } - - // todo implement '.Devices' list related logic from GEaddDevices (devices.c) - @Override - public void registerGraphicsDevice(GraphicsDevice newGraphicsDevice) throws Exception { - if (newGraphicsDevice == null) { - throw new NullPointerException("Graphics device to register is null"); - } - if (!noGraphicsDevices()) { - getCurrentGraphicsDevice().deactivate(); - } - int index = findElementIndexInArray(NULL_GRAPHICS_DEVICE_INDEX + 1, LAST_GRAPHICS_DEVICE_INDEX, null, graphicsDevices); - if (index == NOT_FOUND) { - throw handleErrorAndMakeException("too many open devices"); - } - graphicsDevices[index] = newGraphicsDevice; - devicesAmountWithoutNullDevice++; - currentGraphicsDevice = new CurrentGraphicsDevice(newGraphicsDevice, index); - notifyEachGraphicsSystem(newGraphicsDevice, GE_INIT_STATE); - newGraphicsDevice.activate(); - } - - private void notifyEachGraphicsSystem(GraphicsDevice graphicsDevice, GraphicsEvent event) { - for (int i = 0; i < MAX_GRAPHICS_SYSTEMS_AMOUNT; i++) { - GraphicsSystem graphicsSystem = graphicsSystems[i]; - if (graphicsSystem != null) { - graphicsSystem.getGraphicsEventsListener().onEvent(event, graphicsDevice); - } - } - } - - @Override - public void unRegisterGraphicsDevice(GraphicsDevice deviceToUnregister) { - if (deviceToUnregister == null) { - throw new NullPointerException("Graphics device to unregister is null"); - } - doUnregisterGraphicsDevice(deviceToUnregister); - GraphicsDevice nextGraphicsDevice = getGraphicsDeviceNextTo(deviceToUnregister); - int index = findElementIndexInArray(nextGraphicsDevice, graphicsDevices); - currentGraphicsDevice = new CurrentGraphicsDevice(nextGraphicsDevice, index); - nextGraphicsDevice.activate(); - // todo Interesting that in GNUR a GraphicsSystem is not notified when a GraphicsDevice is - // killed - } - - private void doUnregisterGraphicsDevice(GraphicsDevice deviceToUnregister) { - int index = findElementIndexInArray(deviceToUnregister, graphicsDevices); - if (index == NOT_FOUND) { - issueWarning("no graphics device to unregister"); - return; - } - graphicsDevices[index] = null; - devicesAmountWithoutNullDevice--; - currentGraphicsDevice = new CurrentGraphicsDevice(getNullGraphicsDevice(), NULL_GRAPHICS_DEVICE_INDEX); - deviceToUnregister.close(); - } - - @Override - public int getGraphicsDevicesAmount() { - return devicesAmountWithoutNullDevice; - } - - @Override - public boolean noGraphicsDevices() { - return devicesAmountWithoutNullDevice == 0; - } - - @Override - public int getCurrentGraphicsDeviceIndex() { - return currentGraphicsDevice.graphicsDeviceIndex; - } - - @Override - public GraphicsDevice getCurrentGraphicsDevice() { - if (isNullDeviceIsCurrent()) { - try { - // todo transcribe device installation from GNUR GEcurrentDevice (devices.c) - installCurrentGraphicsDevice(); - } catch (Exception e) { - e.printStackTrace(); - } - } - return currentGraphicsDevice.graphicsDevice; - } - - private boolean isNullDeviceIsCurrent() { - return currentGraphicsDevice.graphicsDevice == getNullGraphicsDevice(); - } - - private void installCurrentGraphicsDevice() throws Exception { - registerGraphicsDevice(new FastRGraphicsDevice()); - } - - @Override - public GraphicsDevice getGraphicsDeviceNextTo(GraphicsDevice graphicsDevice) { - if (graphicsDevice == null) { - throw new NullPointerException("Graphics device is null"); - } - int startIndex = findElementIndexInArray(graphicsDevice, graphicsDevices); - if (startIndex == NOT_FOUND) { - return getNullGraphicsDevice(); - } - GraphicsDevice foundDevice = findNotNullGraphicsDevice(startIndex + 1, graphicsDevices.length, SearchDirection.FORWARD); - if (foundDevice == null) { - foundDevice = findNotNullGraphicsDevice(startIndex - 1, NULL_GRAPHICS_DEVICE_INDEX, SearchDirection.BACKWARD); - } - return foundDevice == null ? getNullGraphicsDevice() : foundDevice; - } - - @Override - public void setCurrentGraphicsDeviceMode(GraphicsDevice.Mode newMode) { - GraphicsDevice currentDevice = getCurrentGraphicsDevice(); - if (currentDevice.getMode() != newMode) { - currentDevice.setMode(newMode); - } - } - - @Override - public GraphicsDevice getGraphicsDevicePrevTo(GraphicsDevice graphicsDevice) { - if (graphicsDevice == null) { - throw new NullPointerException("Graphics device is null"); - } - int startIndex = findElementIndexInArray(graphicsDevice, graphicsDevices); - if (startIndex == NOT_FOUND) { - return getNullGraphicsDevice(); - } - GraphicsDevice foundDevice = findNotNullGraphicsDevice(startIndex - 1, NULL_GRAPHICS_DEVICE_INDEX, SearchDirection.BACKWARD); - if (foundDevice == null) { - foundDevice = findNotNullGraphicsDevice(startIndex + 1, graphicsDevices.length, SearchDirection.FORWARD); - } - return foundDevice == null ? getNullGraphicsDevice() : foundDevice; - } - - private static <T> int findElementIndexInArray(T element, T[] array) { - return findElementIndexInArray(0, array.length, element, array); - } - - private static <T> int findElementIndexInArray(int startIndexInclusive, int endIndexNotInclusive, T element, T[] array) { - for (int i = startIndexInclusive; i < endIndexNotInclusive; i++) { - if (array[i] == element) { - return i; - } - } - return NOT_FOUND; - } - - private GraphicsDevice findNotNullGraphicsDevice(int startIndexInclusive, int endIndexNotInclusive, SearchDirection direction) { - switch (direction) { - case FORWARD: - for (int i = startIndexInclusive; i < endIndexNotInclusive; i++) { - GraphicsDevice graphicsDevice = graphicsDevices[i]; - if (graphicsDevice != null) { - return graphicsDevice; - } - } - break; - case BACKWARD: - for (int i = startIndexInclusive; i > endIndexNotInclusive; i--) { - GraphicsDevice graphicsDevice = graphicsDevices[i]; - if (graphicsDevice != null) { - return graphicsDevice; - } - } - } - return getNullGraphicsDevice(); - } - - private GraphicsDevice getNullGraphicsDevice() { - return graphicsDevices[NULL_GRAPHICS_DEVICE_INDEX]; - } - - @Override - public void setCurrentGraphicsDeviceClipRect(double x1, double y1, double x2, double y2) { - // todo transcribe from GESetClip() (engine.c) - getCurrentGraphicsDevice().setClipRect(0, 0, 0, 0); - } - - @Override - public void drawPolyline(Coordinates coordinates, DrawingParameters drawingParameters) { - getCurrentGraphicsDevice().drawPolyline(coordinates, drawingParameters); - } - - @Override - public void killGraphicsDeviceByIndex(int graphicsDeviceIndex) { - // todo TBD - } - - private final class CurrentGraphicsDevice { - private final GraphicsDevice graphicsDevice; - private final int graphicsDeviceIndex; - - private CurrentGraphicsDevice(GraphicsDevice graphicsDevice, int graphicsDeviceIndex) { - this.graphicsDevice = graphicsDevice; - this.graphicsDeviceIndex = graphicsDeviceIndex; - } - } - - private enum SearchDirection { - FORWARD, - BACKWARD - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEvent.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEvent.java deleted file mode 100644 index 5ff9cf1c50ef0a89089439190ac045e43bac3521..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEvent.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics.core; - -public enum GraphicsEvent { - GE_INIT_STATE, - GE_FINAL_STATE -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystem.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystem.java deleted file mode 100644 index d0011a8c9a42eb6c9af5976901e6d20a283bea67..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystem.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics.core; - -public interface GraphicsSystem { - GraphicsEventsListener getGraphicsEventsListener(); - - void setId(int id); - - int getId(); - - public interface GraphicsEventsListener { - void onEvent(GraphicsEvent graphicsEvent, GraphicsDevice graphicsDevice); - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystemParameters.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystemParameters.java deleted file mode 100644 index 4d3ead19cad9736f8048aa38d04083add1bc47e4..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystemParameters.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics.core; - -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.Map; - -class GraphicsSystemParameters { - private final Map<GraphicsDevice, HashMap<String, Object>> parametersByDevices = new IdentityHashMap<>(); - - void addParameterForDevice(GraphicsDevice graphicsDevice, String parameterName, Object parameterValue) { - HashMap<String, Object> parameters = parametersByDevices.get(graphicsDevice); - if (parameters == null) { - parameters = new HashMap<>(); - parametersByDevices.put(graphicsDevice, parameters); - } - parameters.put(parameterName, parameterValue); - } - - Object getParameterForDevice(GraphicsDevice graphicsDevice, int parameterName) { - HashMap<String, Object> parameters = parametersByDevices.get(graphicsDevice); - return parameters == null ? null : parameters.get(parameterName); - } - - void removeAllParametersForDevice(GraphicsDevice graphicsDevice) { - parametersByDevices.remove(graphicsDevice); - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/CoordinatesDrawableObject.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/CoordinatesDrawableObject.java deleted file mode 100644 index 4f641d7a79cf822ec0291cb4722a212e2d260587..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/CoordinatesDrawableObject.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics.core.drawables; - -import com.oracle.truffle.r.library.graphics.core.geometry.CoordinateSystem; -import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates; -import com.oracle.truffle.r.library.graphics.core.geometry.IntCoordinates; - -/** - * Denotes an object which drawing depends only from {@link Coordinates}. And automates conversion - * from <code>srcCoordinates</code> to <code>dstCoordinates</code>. - */ -public abstract class CoordinatesDrawableObject extends DrawableObject { - private final Coordinates srcCoordinates; - - private Coordinates dstCoordinates; - - protected CoordinatesDrawableObject(CoordinateSystem coordinateSystem, Coordinates coordinates) { - super(coordinateSystem); - this.srcCoordinates = coordinates; - } - - @Override - public void recalculateForDrawingIn(CoordinateSystem dstCoordinateSystem) { - Coordinates converted = dstCoordinateSystem.convertCoordinatesFrom(getSrcCoordinateSystem(), srcCoordinates); - dstCoordinates = new IntCoordinates(converted.getXCoordinatesAsInts(), converted.getYCoordinatesAsInts()); - } - - protected final Coordinates getDstCoordinates() { - return dstCoordinates; - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/DrawableObject.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/DrawableObject.java deleted file mode 100644 index ec4b0d5824ce7d9b9c677c3884b9755c06898c5d..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/DrawableObject.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2016, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics.core.drawables; - -import java.awt.Graphics2D; - -import com.oracle.truffle.r.library.graphics.core.geometry.CoordinateSystem; - -/** - * Denotes an object defined in <code>srcCoordinateSystem</code> that can be drawn in - * <code>dstCoordinateSystem</code> on {@link Graphics2D}. - */ -public abstract class DrawableObject { - private final CoordinateSystem srcCoordinateSystem; - - protected DrawableObject(CoordinateSystem srcCoordinateSystem) { - this.srcCoordinateSystem = srcCoordinateSystem; - } - - public abstract void drawOn(Graphics2D g2); - - /** - * Override to prepare coordinates given in <code>srcCoordinateSystem</code> to be drawn in - * <code>srcCoordinateSystem</code>. - */ - public abstract void recalculateForDrawingIn(CoordinateSystem dstCoordinateSystem); - - protected final CoordinateSystem getSrcCoordinateSystem() { - return srcCoordinateSystem; - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/PolylineDrawableObject.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/PolylineDrawableObject.java deleted file mode 100644 index 2cf12e7f6aed8572cb9334b8d4241a24dd505012..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/PolylineDrawableObject.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2016, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics.core.drawables; - -import java.awt.Graphics2D; - -import com.oracle.truffle.r.library.graphics.core.geometry.CoordinateSystem; -import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates; - -/** - * Able to draw a polyline on {@link Graphics2D}. - */ -public class PolylineDrawableObject extends CoordinatesDrawableObject { - public PolylineDrawableObject(CoordinateSystem coordinateSystem, Coordinates coordinates) { - super(coordinateSystem, coordinates); - } - - @Override - public void drawOn(Graphics2D g2) { - Coordinates coords = getDstCoordinates(); - int[] xCoords = coords.getXCoordinatesAsInts(); - g2.drawPolyline(xCoords, coords.getYCoordinatesAsInts(), xCoords.length); - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/StringDrawableObject.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/StringDrawableObject.java deleted file mode 100644 index ccf4e16876bbd90c3b576366407838592916ff4f..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/StringDrawableObject.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2016, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics.core.drawables; - -import java.awt.Graphics2D; -import java.util.stream.IntStream; - -import com.oracle.truffle.r.library.graphics.core.geometry.CoordinateSystem; -import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates; - -/** - * Able to render a text on {@link Graphics2D}. - */ -public class StringDrawableObject extends CoordinatesDrawableObject { - private final String[] strings; - - public StringDrawableObject(CoordinateSystem coordinateSystem, Coordinates coordinates, String[] strings) { - super(coordinateSystem, coordinates); - this.strings = strings; - } - - @Override - public void drawOn(Graphics2D g2) { - Coordinates dstCoordinates = getDstCoordinates(); - int[] xCoords = dstCoordinates.getXCoordinatesAsInts(); - int[] yCoords = dstCoordinates.getYCoordinatesAsInts(); - IntStream.range(0, strings.length).forEach(i -> g2.drawString(strings[i], xCoords[i], yCoords[i])); - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/Axis.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/Axis.java deleted file mode 100644 index c9a33c65a82da57a5b2f57a5fb1c65dbc2203be4..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/Axis.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics.core.geometry; - -public final class Axis { - private final double minValue; - private final double maxValue; - private final AxisDirection direction; - - public Axis(double minValue, double maxValue, AxisDirection direction) { - this.minValue = minValue; - this.maxValue = maxValue; - this.direction = direction; - } - - public double getMinValue() { - return minValue; - } - - public double getMaxValue() { - return maxValue; - } - - public AxisDirection getDirection() { - return direction; - } - - public double getRange() { - return maxValue - minValue; - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/AxisDirection.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/AxisDirection.java deleted file mode 100644 index 8099a58058eae00db737d42cc2c75a918ff9fcb0..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/AxisDirection.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics.core.geometry; - -public enum AxisDirection { - NORTH, - SOUTH, - WEST, - EAST -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/CoordinateSystem.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/CoordinateSystem.java deleted file mode 100644 index 2c1fca3b817a003160c798290ea87c1d93c0d7f2..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/CoordinateSystem.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics.core.geometry; - -import java.util.stream.DoubleStream; - -/** - * Denotes X-Y coordinate system by specifying max and min values for X-Y axis. Able to convert - * coordinates given in another {@link CoordinateSystem} - */ -public final class CoordinateSystem { - private final Axis xAxis; - private final Axis yAxis; - - /** - * Uses Java graphics default axis orientation: x increases to the right, y increases to the - * bottom. - */ - public CoordinateSystem(double minX, double maxX, double minY, double maxY) { - this(minX, maxX, minY, maxY, AxisDirection.EAST, AxisDirection.SOUTH); - } - - public CoordinateSystem(double minX, double maxX, double minY, double maxY, AxisDirection xDirection, AxisDirection yDirection) { - this(new Axis(minX, maxX, xDirection), new Axis(minY, maxY, yDirection)); - } - - public CoordinateSystem(Axis xAxis, Axis yAxis) { - this.xAxis = xAxis; - this.yAxis = yAxis; - } - - /** - * Transforms <code> otherCoordinates </code> given in <code> otherCoordinateSystem</code> to - * this coordinate system. Also applies the affine transformation defined by ratio and shifts. - */ - public Coordinates convertCoordinatesFrom(CoordinateSystem otherCoordinateSystem, Coordinates otherCoordinates, double ratio, double xAxisShift, double yAxisShift) { - double[] resultX = convertCoordinatesBetweenAxises(getXAxis(), otherCoordinateSystem.getXAxis(), otherCoordinates.getXCoordinatesAsDoubles(), ratio, xAxisShift); - double[] resultY = convertCoordinatesBetweenAxises(getYAxis(), otherCoordinateSystem.getYAxis(), otherCoordinates.getYCoordinatesAsDoubles(), ratio, yAxisShift); - return new DoubleCoordinates(resultX, resultY); - } - - public Coordinates convertCoordinatesFrom(CoordinateSystem otherCoordinateSystem, Coordinates otherCoordinates) { - double noRatio = 1; - double noShift = 0; - return convertCoordinatesFrom(otherCoordinateSystem, otherCoordinates, noRatio, noShift, noShift); - } - - private static double[] convertCoordinatesBetweenAxises(Axis toAxis, Axis fromAxis, double[] coords, double givenRatio, double givenShift) { - boolean sameDirection = toAxis.getDirection() == fromAxis.getDirection(); - double ratio = toAxis.getRange() / fromAxis.getRange(); - ratio = sameDirection ? ratio : -ratio; - ratio *= givenRatio; // adding given ratio - double shift = sameDirection ? 0 : toAxis.getMaxValue(); - shift += givenShift * ratio; // adding given shift - return applyShiftAndRatio(coords, ratio, shift); - } - - private static double[] applyShiftAndRatio(double[] coords, double ratio, double shift) { - return DoubleStream.of(coords).map(d -> d * ratio + shift).toArray(); - } - - private Axis getXAxis() { - return xAxis; - } - - private Axis getYAxis() { - return yAxis; - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/Coordinates.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/Coordinates.java deleted file mode 100644 index 95396232f26e67252041de67b3653756097f7c7c..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/Coordinates.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics.core.geometry; - -/** - * Denotes X-Y coordinates. Instances must be immutable objects. - */ -public interface Coordinates { - double[] getXCoordinatesAsDoubles(); - - double[] getYCoordinatesAsDoubles(); - - int[] getXCoordinatesAsInts(); - - int[] getYCoordinatesAsInts(); -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/CoordinatesFactory.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/CoordinatesFactory.java deleted file mode 100644 index 33e81bb144b46109300d75c7c5881ace2e86b41b..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/CoordinatesFactory.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2016, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics.core.geometry; - -import java.util.Arrays; -import java.util.stream.DoubleStream; -import java.util.stream.IntStream; - -import com.oracle.truffle.r.runtime.data.RDoubleVector; - -public final class CoordinatesFactory { - private CoordinatesFactory() { - } - - public static DoubleCoordinates createWithSameX(double x, double[] yCoords) { - double[] xCoords = createdFilledArray(x, yCoords.length); - return new DoubleCoordinates(xCoords, yCoords); - } - - public static DoubleCoordinates createWithSameY(double[] xCoords, double y) { - double[] yCoords = createdFilledArray(y, xCoords.length); - return new DoubleCoordinates(xCoords, yCoords); - } - - private static double[] createdFilledArray(double value, int size) { - double[] result = new double[size]; - Arrays.fill(result, value); - return result; - } - - public static DoubleCoordinates createByXYVector(RDoubleVector xyVector) { - int length = xyVector.getLength(); - double[] xCoords = IntStream.range(0, length).filter(i -> i % 2 == 0).mapToDouble(xyVector::getDataAt).toArray(); - double[] yCoords = IntStream.range(0, length).filter(i -> i % 2 != 0).mapToDouble(xyVector::getDataAt).toArray(); - return new DoubleCoordinates(xCoords, yCoords); - } - - public static DoubleCoordinates createByXYPairs(double[] xyPairs) { - int length = xyPairs.length; - double[] xCoords = IntStream.range(0, length).filter(i -> i % 2 == 0).mapToDouble(i -> xyPairs[i]).toArray(); - double[] yCoords = IntStream.range(0, length).filter(i -> i % 2 != 0).mapToDouble(i -> xyPairs[i]).toArray(); - return new DoubleCoordinates(xCoords, yCoords); - } - - public static DoubleCoordinates withRatioAndShift(Coordinates coordinates, double ratio, double shift) { - return withRatioAndShift(coordinates, ratio, shift, shift); - } - - public static DoubleCoordinates withRatioAndShift(Coordinates coordinates, double ratio, double xShift, double yShift) { - double[] convertedX = applyRatioAndShiftTo(coordinates.getXCoordinatesAsDoubles(), ratio, xShift); - double[] convertedY = applyRatioAndShiftTo(coordinates.getYCoordinatesAsDoubles(), ratio, yShift); - return new DoubleCoordinates(convertedX, convertedY); - } - - private static double[] applyRatioAndShiftTo(double[] coordinates, double ratio, double shift) { - return DoubleStream.of(coordinates).map(d -> d * ratio + shift).toArray(); - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/DoubleCoordinates.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/DoubleCoordinates.java deleted file mode 100644 index 90dcb51dd61f9b8f234b097f6b5ff97531aff1af..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/DoubleCoordinates.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2016, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics.core.geometry; - -import java.util.stream.DoubleStream; - -public final class DoubleCoordinates implements Coordinates { - - private final double[] xCoords; - private final double[] yCoords; - - public DoubleCoordinates(double[] xCoords, double[] yCoords) { - this.xCoords = xCoords; - this.yCoords = yCoords; - } - - @Override - public double[] getXCoordinatesAsDoubles() { - return xCoords; - } - - @Override - public double[] getYCoordinatesAsDoubles() { - return yCoords; - } - - @Override - public int[] getXCoordinatesAsInts() { - return toInt(getXCoordinatesAsDoubles()); - } - - @Override - public int[] getYCoordinatesAsInts() { - return toInt(getYCoordinatesAsDoubles()); - } - - private static int[] toInt(double[] doubleArray) { - return DoubleStream.of(doubleArray).mapToInt(d -> (int) d).toArray(); - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/IntCoordinates.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/IntCoordinates.java deleted file mode 100644 index cd62ef35fe6eca47082d6314c2852f7daec5f8c1..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/IntCoordinates.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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) 1995, 1996 Robert Gentleman and Ross Ihaka - * Copyright (C) 1998 Ross Ihaka - * Copyright (c) 1998--2014, The R Core Team - * Copyright (c) 2002--2010, The R Foundation - * Copyright (C) 2005--2006, Morten Welinder - * Copyright (c) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.graphics.core.geometry; - -import java.util.stream.IntStream; - -public final class IntCoordinates implements Coordinates { - private final int[] xCoords; - private final int[] yCoords; - - public IntCoordinates(int[] xCoords, int[] yCoords) { - this.xCoords = xCoords; - this.yCoords = yCoords; - } - - @Override - public double[] getXCoordinatesAsDoubles() { - return toDouble(xCoords); - } - - @Override - public double[] getYCoordinatesAsDoubles() { - return toDouble(yCoords); - } - - @Override - public int[] getXCoordinatesAsInts() { - return xCoords; - } - - @Override - public int[] getYCoordinatesAsInts() { - return yCoords; - } - - private static double[] toDouble(int[] intArray) { - return IntStream.of(intArray).mapToDouble(i -> i).toArray(); - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java deleted file mode 100644 index 6623a2c7ca6a8538ce7bbe35792f2b8f5c18294e..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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) 2001-3 Paul Murrell - * Copyright (c) 1998-2013, The R Core Team - * Copyright (c) 2013, 2017, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.library.grid; - -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; - -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.Fallback; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; -import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RIntVector; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.env.REnvironment; -import com.oracle.truffle.r.runtime.ffi.GridRFFI; -import com.oracle.truffle.r.runtime.ffi.RFFIFactory; - -/** - * The .Call support for the grid package. - */ -public class GridFunctions { - - public abstract static class InitGrid extends RExternalBuiltinNode.Arg1 { - @Child GridRFFI.InitGridNode initGridNode = RFFIFactory.getRFFI().getGridRFFI().createInitGridNode(); - - @Specialization - @TruffleBoundary - protected Object initGrid(REnvironment gridEvalEnv) { - return initGridNode.execute(gridEvalEnv); - } - - @Fallback - protected Object initGridFallback(@SuppressWarnings("unused") Object x) { - return RNull.instance; - } - } - - public static final class KillGrid extends RExternalBuiltinNode { - @Child GridRFFI.KillGridNode killGridNode = RFFIFactory.getRFFI().getGridRFFI().createKillGridNode(); - - static { - Casts.noCasts(KillGrid.class); - } - - @Override - @TruffleBoundary - public Object call(RArgsValuesAndNames args) { - return killGridNode.execute(); - } - } - - public abstract static class ValidUnits extends RExternalBuiltinNode.Arg1 { - - static { - Casts casts = new Casts(ValidUnits.class); - casts.arg(0).mustBe(stringValue(), RError.Message.GENERIC, "'units' must be character").asStringVector().mustBe(notEmpty(), RError.Message.GENERIC, "'units' must be of length > 0"); - } - - @Specialization - protected RIntVector validUnits(RAbstractStringVector units) { - int[] data = new int[units.getLength()]; - for (int i = 0; i < data.length; i++) { - int code = convertUnit(units.getDataAt(i)); - if (code < 0) { - throw RError.error(this, RError.Message.GENERIC, "Invalid unit"); - } - data[i] = code; - } - return RDataFactory.createIntVector(data, RDataFactory.COMPLETE_VECTOR); - } - - private enum UnitTab { - npc(0); - - private final int code; - - UnitTab(int code) { - this.code = code; - } - } - - private static int convertUnit(String unit) { - for (UnitTab unitTab : UnitTab.values()) { - if (unit.equals(unitTab.name())) { - return unitTab.code; - } - } - return -1; - } - } -} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java index 48f6249fe47be0de70c34485090586d4674ca342..5ec3a485350a46e226516c39801a6203aeac81d3 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java @@ -59,6 +59,7 @@ import com.oracle.truffle.r.runtime.data.RS4Object; import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RNode; @@ -72,12 +73,12 @@ public class MethodsListDispatch { Function<Object, Integer> vecLenFn) { //@formatter:off casts.arg(argNum, argName). - defaultError(RError.NO_CALLER, RError.Message.SINGLE_STRING_WRONG_TYPE, msg, clsHierFn). + defaultError(RError.Message.SINGLE_STRING_WRONG_TYPE, msg, clsHierFn). mustBe(stringValue()). asStringVector(). - mustBe(singleElement(), RError.NO_CALLER, RError.Message.SINGLE_STRING_TOO_LONG, msg, vecLenFn). + mustBe(singleElement(), RError.Message.SINGLE_STRING_TOO_LONG, msg, vecLenFn). findFirst(). - mustBe(nonEmpty ? lengthGt(0) : lengthGte(0), RError.NO_CALLER, RError.Message.NON_EMPTY_STRING, msg); + mustBe(nonEmpty ? lengthGt(0) : lengthGte(0), RError.Message.NON_EMPTY_STRING, msg); //@formatter:on } @@ -130,8 +131,7 @@ public class MethodsListDispatch { static { Casts casts = new Casts(R_getClassFromCache.class); casts.arg(0, "klass").defaultError(RError.Message.GENERIC, "class should be either a character-string name or a class definition").mustBe(stringValue().or(instanceOf(RS4Object.class))); - - casts.arg(1, "table").mustNotBeNull(RError.NO_CALLER, RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class)); + casts.arg(1, "table").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class)); } protected GetFixedAttributeNode createPckgAttrAccess() { @@ -146,7 +146,7 @@ public class MethodsListDispatch { String klassString = klass.getLength() == 0 ? RRuntime.STRING_NA : klass.getDataAt(0); if (klassString.length() == 0) { - throw RError.error(RError.NO_CALLER, RError.Message.ZERO_LENGTH_VARIABLE); + throw error(RError.Message.ZERO_LENGTH_VARIABLE); } Object value = table.get(klassString); @@ -240,7 +240,7 @@ public class MethodsListDispatch { String internalName = RRuntime.asString(initAccessSlotNode().executeAccess(op, "internal")); opx = RContext.lookupBuiltin(internalName); if (opx == null) { - throw RError.error(this, RError.Message.GENERIC, "'internal' slot does not name an internal function: " + internalName); + throw error(RError.Message.GENERIC, "'internal' slot does not name an internal function: " + internalName); } } @@ -248,7 +248,7 @@ public class MethodsListDispatch { return fnameString; } - private static void setPrimitiveMethodsInternal(Object op, String codeVec, RTypedValue fundef, Object mlist) { + private void setPrimitiveMethodsInternal(Object op, String codeVec, RTypedValue fundef, Object mlist) { MethodCode code; if (codeVec.charAt(0) == 'c') { code = MethodCode.NO_METHODS; @@ -259,10 +259,10 @@ public class MethodsListDispatch { } else if (codeVec.startsWith("su")) { code = MethodCode.SUPPRESSED; } else { - throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_PRIM_METHOD_CODE, codeVec); + throw error(RError.Message.INVALID_PRIM_METHOD_CODE, codeVec); } if (!(op instanceof RFunction) || !((RFunction) op).isBuiltin()) { - throw RError.error(RError.SHOW_CALLER, RError.Message.GENERIC, "invalid object: must be a primitive function"); + throw error(RError.Message.GENERIC, "invalid object: must be a primitive function"); } int primMethodIndex = ((RFunction) op).getRBuiltin().getPrimMethodIndex(); assert primMethodIndex != PrimitiveMethodsInfo.INVALID_INDEX; @@ -280,7 +280,7 @@ public class MethodsListDispatch { primMethodsInfo.setPrimMethodList(primMethodIndex, null); } else if (fundef != RNull.instance && value == null) { if (!(fundef instanceof RFunction)) { - throw RError.error(RError.SHOW_CALLER, RError.Message.PRIM_GENERIC_NOT_FUNCTION, fundef.getRType().getName()); + throw error(RError.Message.PRIM_GENERIC_NOT_FUNCTION, fundef.getRType().getName()); } primMethodsInfo.setPrimGeneric(primMethodIndex, (RFunction) fundef); } @@ -327,7 +327,7 @@ public class MethodsListDispatch { checkSingleString(casts, 0, "f", "The argument \"f\" to getGeneric", true, clsHierFn, vecLenFn); - casts.arg(1, "mustFind").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean()); + casts.arg(1, "mustFind").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); casts.arg(2, "env").mustBe(instanceOf(REnvironment.class)); @@ -340,9 +340,9 @@ public class MethodsListDispatch { if (value == RNull.instance) { if (mustFind) { if (env == RContext.getInstance().stateREnvironment.getGlobalEnv()) { - throw RError.error(RError.NO_CALLER, RError.Message.NO_GENERIC_FUN, name); + throw error(RError.Message.NO_GENERIC_FUN, name); } else { - throw RError.error(RError.NO_CALLER, RError.Message.NO_GENERIC_FUN_IN_ENV, name); + throw error(RError.Message.NO_GENERIC_FUN_IN_ENV, name); } } } @@ -379,7 +379,7 @@ public class MethodsListDispatch { if (pckg.length() > 0) { Object gpckgObj = getPckgAttrNode.execute(vl); if (gpckgObj != null) { - String gpckg = checkSingleString(castToVector.execute(gpckgObj), false, "The \"package\" slot in generic function object", this, classHierarchyNode); + String gpckg = checkSingleString(castToVector.doCast(gpckgObj), false, "The \"package\" slot in generic function object", this, classHierarchyNode); ok = pckg.equals(gpckg); } } else { @@ -408,11 +408,11 @@ public class MethodsListDispatch { } String s = vec.getDataAt(0); if (nonEmpty && s.length() == 0) { - throw RError.error(node, RError.Message.NON_EMPTY_STRING, what); + throw node.error(RError.Message.NON_EMPTY_STRING, what); } return s; } else { - throw RError.error(node, RError.Message.SINGLE_STRING_WRONG_TYPE, what, classHierarchyNode.executeString(o)); + throw node.error(RError.Message.SINGLE_STRING_WRONG_TYPE, what, classHierarchyNode.executeString(o)); } } @@ -420,7 +420,7 @@ public class MethodsListDispatch { private static Object slotRead(MaterializedFrame currentFrame, FrameDescriptor desc, String name) { FrameSlot slot = desc.findFrameSlot(name); if (slot != null) { - Object res = currentFrame.getValue(slot); + Object res = FrameSlotChangeMonitor.getValue(slot, currentFrame); if (res != null) { if (res instanceof RPromise) { res = PromiseHelperNode.evaluateSlowPath(null, (RPromise) res); @@ -453,7 +453,7 @@ public class MethodsListDispatch { RFunction op = (RFunction) readDotNextMethod.execute(null, ev.getFrame()); if (op == null) { - throw RError.error(this, RError.Message.GENERIC, "internal error in 'callNextMethod': '.nextMethod' was not assigned in the frame of the method call"); + throw error(RError.Message.GENERIC, "internal error in 'callNextMethod': '.nextMethod' was not assigned in the frame of the method call"); } boolean primCase = op.isBuiltin(); if (primCase) { diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java index 51803d72d1764bc80f4c6244ec3e2eec40ee7c1d..741c70902416f676b80ebb64b405effafc205a6c 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java @@ -38,8 +38,8 @@ public class Slot { static { Casts casts = new Casts(R_getSlot.class); - casts.arg(1, "name").defaultError(RError.NO_CALLER, RError.Message.GENERIC, "invalid type or length for slot name").mustBe(stringValue()).asStringVector().mustBe( - singleElement()).findFirst().mustBe(Predef.lengthGt(0), RError.NO_CALLER, RError.Message.ZERO_LENGTH_VARIABLE); + casts.arg(1, "name").defaultError(RError.Message.GENERIC, "invalid type or length for slot name").mustBe(stringValue()).asStringVector().mustBe( + singleElement()).findFirst().mustBe(Predef.lengthGt(0), RError.Message.ZERO_LENGTH_VARIABLE); } protected static String getInternedName(String name) { @@ -66,8 +66,8 @@ public class Slot { static { Casts casts = new Casts(R_setSlot.class); - casts.arg(1, "name").defaultError(RError.NO_CALLER, RError.Message.GENERIC, "invalid type or length for slot name").mustBe(stringValue()).asStringVector().mustBe( - singleElement()).findFirst().mustBe(Predef.lengthGt(0), RError.NO_CALLER, RError.Message.ZERO_LENGTH_VARIABLE); + casts.arg(1, "name").defaultError(RError.Message.GENERIC, "invalid type or length for slot name").mustBe(stringValue()).asStringVector().mustBe( + singleElement()).findFirst().mustBe(Predef.lengthGt(0), RError.Message.ZERO_LENGTH_VARIABLE); } protected static String getInternedName(String name) { diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java index e1a2b1bac6bd9299591dc2e0b6c11c65f8a70994..0bd6d97f09823da2e2123a82c5f5d042aeefbcde 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java @@ -32,19 +32,24 @@ import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.nodes.builtin.RList2EnvNode; import com.oracle.truffle.r.runtime.RError; import static com.oracle.truffle.r.runtime.RError.Message.INVALID_LIST_FOR_SUBSTITUTION; -import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; import com.oracle.truffle.r.runtime.RSubstitute; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; public abstract class SubstituteDirect extends RExternalBuiltinNode.Arg2 { static { Casts casts = new Casts(SubstituteDirect.class); - casts.arg(1).defaultError(SHOW_CALLER, INVALID_LIST_FOR_SUBSTITUTION).mustBe(instanceOf(RAbstractListVector.class).or(instanceOf(REnvironment.class))); + casts.arg(1).defaultError(INVALID_LIST_FOR_SUBSTITUTION).mustBe(instanceOf(RAbstractListVector.class).or(instanceOf(REnvironment.class))); + } + + @Override + protected RBaseNode getErrorContext() { + return RError.SHOW_CALLER; } @Specialization @@ -60,7 +65,7 @@ public abstract class SubstituteDirect extends RExternalBuiltinNode.Arg2 { @Specialization(guards = {"list.getNames() == null || list.getNames().getLength() == 0"}) @TruffleBoundary - protected static Object substituteDirect(Object object, RList list) { + protected static Object substituteDirect(Object object, @SuppressWarnings("unused") RList list) { return substituteDirect(object, createNewEnvironment()); } @@ -73,7 +78,7 @@ public abstract class SubstituteDirect extends RExternalBuiltinNode.Arg2 { @Fallback protected Object substituteDirect(@SuppressWarnings("unused") Object object, @SuppressWarnings("unused") Object env) { - throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); + throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); } @TruffleBoundary diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/BinDist.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/BinDist.java index a5b037c3844d5de7a3bd08403d207286ba008bb7..bb15916f20f26b17dcf579044a067fe2613107fe 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/BinDist.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/BinDist.java @@ -15,9 +15,11 @@ */ package com.oracle.truffle.r.library.stats; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleVector; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gt0; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.intNA; -import static com.oracle.truffle.r.runtime.RError.NO_CALLER; import java.util.Arrays; @@ -39,11 +41,11 @@ public abstract class BinDist extends RExternalBuiltinNode.Arg5 { static { Casts casts = new Casts(BinDist.class); - casts.arg(0).asDoubleVector(); - casts.arg(1).asDoubleVector(); + casts.arg(0).mustBe(missingValue().not()).returnIf(nullValue(), emptyDoubleVector()).asDoubleVector(); + casts.arg(1).mustBe(missingValue().not()).returnIf(nullValue(), emptyDoubleVector()).asDoubleVector(); casts.arg(2).asDoubleVector().findFirst(); casts.arg(3).asDoubleVector().findFirst(); - casts.arg(4).asIntegerVector().findFirst().mustBe(gt0().and(intNA().not()), NO_CALLER, Message.INVALID_ARGUMENT, "n"); + casts.arg(4).asIntegerVector().findFirst().mustBe(gt0().and(intNA().not()), Message.INVALID_ARGUMENT, "n"); } @Specialization diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java index be4422e729caa2e552fa45586ccb92bdd6a0dfad..47a820c41aa22f757c6aeb7ab398585251bf28c8 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java @@ -12,6 +12,8 @@ */ package com.oracle.truffle.r.library.stats; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; import static com.oracle.truffle.r.runtime.nmath.MathConstants.DBL_MIN; @@ -39,7 +41,7 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { static { Casts casts = new Casts(Cdist.class); - casts.arg(0).asDoubleVector(); + casts.arg(0).mustBe(nullValue().not(), RError.Message.VECTOR_IS_TOO_LARGE).mustBe(missingValue().not()).asDoubleVector(); casts.arg(1).asIntegerVector().findFirst(); casts.arg(2).mustBe(instanceOf(RList.class)); casts.arg(3).asDoubleVector().findFirst(); @@ -61,13 +63,15 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { DynamicObject resultAttrs = result.initAttributes(); RStringVector names = (RStringVector) getNamesAttrNode.execute(list); - for (int i = 0; i < names.getLength(); i++) { - String name = names.getDataAt(i); - Object listValue = list.getDataAt(i); - if (name.equals(RRuntime.CLASS_ATTR_KEY)) { - setClassAttrNode.execute(result, listValue instanceof RStringVector ? (RStringVector) listValue : RDataFactory.createStringVectorFromScalar((String) listValue)); - } else { - setAttrNode.execute(resultAttrs, name, listValue); + if (names != null) { + for (int i = 0; i < names.getLength(); i++) { + String name = names.getDataAt(i); + Object listValue = list.getDataAt(i); + if (name.equals(RRuntime.CLASS_ATTR_KEY)) { + setClassAttrNode.execute(result, listValue instanceof RStringVector ? (RStringVector) listValue : RDataFactory.createStringVectorFromScalar((String) listValue)); + } else { + setAttrNode.execute(resultAttrs, name, listValue); + } } } @@ -82,19 +86,19 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { return RRuntime.isFinite(a) && RRuntime.isFinite(b); } - public static Method getMethod(int method) { + public Method getMethod(int method) { if (method < 1 || method > Method.values().length) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "distance(): invalid distance"); + throw error(RError.Message.GENERIC, "distance(): invalid distance"); } return Method.values()[method - 1]; } - private static void rdistance(double[] x, int nr, int nc, double[] d, boolean diag, Method method, double p) { + private void rdistance(double[] x, int nr, int nc, double[] d, boolean diag, Method method, double p) { int ij; /* can exceed 2^31 - 1, but Java can't handle that */ // if (method == Method.MINKOWSKI) { if (!RRuntime.isFinite(p) || p <= 0) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "distance(): invalid p"); + throw error(RError.Message.GENERIC, "distance(): invalid p"); } } int dc = diag ? 0 : 1; /* diag=1: we do the diagonal */ diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java index ca606b38331ece53d38741ea3374379b24b950d2..1b7b81345c61a2dee531da2469918a904077780f 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java @@ -39,11 +39,11 @@ public final class CompleteCases extends RExternalBuiltinNode { } private RError invalidType(Object entry) { - throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, ((RTypedValue) entry).getRType().getName()); + throw error(RError.Message.INVALID_TYPE_ARGUMENT, ((RTypedValue) entry).getRType().getName()); } private RError lengthMismatch() { - throw RError.error(this, RError.Message.NOT_ALL_SAME_LENGTH); + throw error(RError.Message.NOT_ALL_SAME_LENGTH); } private int checkAbstractVectorLength(int len, Object obj) { @@ -95,7 +95,7 @@ public final class CompleteCases extends RExternalBuiltinNode { } if (len < 0) { - throw RError.error(this, RError.Message.NO_INPUT_NUMBER_OF_CASES); + throw error(RError.Message.NO_INPUT_NUMBER_OF_CASES); } byte[] result = new byte[len]; diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java index 05fc0538c7b25a639621064b0dea4015ba5a49b9..7e9d9c2c63e33d6457db83931b5fd92591c2e6bf 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java @@ -11,10 +11,9 @@ */ package com.oracle.truffle.r.library.stats; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.eq; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; -import static com.oracle.truffle.r.runtime.RError.NO_CALLER; -import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; import java.util.Arrays; @@ -48,8 +47,8 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 { static { Casts casts = new Casts(Covcor.class); - casts.arg(0).mustNotBeNull(SHOW_CALLER, Message.IS_NULL, "x").asDoubleVector(); - casts.arg(1).asDoubleVector(); + casts.arg(0).mustNotBeMissing().mustBe(nullValue().not(), Message.IS_NULL, "x").asDoubleVector(); + casts.arg(1).mustNotBeMissing().asDoubleVector(); casts.arg(2).asIntegerVector().findFirst().mustBe(eq(4), Message.NYI, "covcor: other method than 4 not implemented."); casts.arg(3).asLogicalVector().findFirst().map(toBoolean()); } @@ -99,14 +98,14 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 { } else if (getDimsNode.isMatrix(y)) { if (nrows(y) != n) { error.enter(); - error("incompatible dimensions"); + throw error("incompatible dimensions"); } ncy = ncols(y); ansmat = true; } else { if (y.getLength() != n) { error.enter(); - error("incompatible dimensions"); + throw error("incompatible dimensions"); } ncy = 1; } @@ -124,7 +123,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 { if (emptyErr && x.getLength() == 0) { error.enter(); - error("'x' is empty"); + throw error("'x' is empty"); } double[] answerData = new double[ncx * ncy]; @@ -194,7 +193,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 { for (i = 0; i < n; i++) { if (Double.isNaN(x.getDataAt(j * n + i))) { if (naFail) { - error("missing observations in cov/cor"); + throw error("missing observations in cov/cor"); } else { ind.updateDataAt(i, 0, check); } @@ -214,7 +213,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 { for (i = 0; i < n; i++) { if (Double.isNaN(x.getDataAt(j * n + i))) { if (naFail) { - error("missing observations in cov/cor"); + throw error("missing observations in cov/cor"); } else { ind.updateDataAt(i, 0, check); } @@ -227,7 +226,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 { for (i = 0; i < n; i++) { if (Double.isNaN(y.getDataAt(j * n + i))) { if (naFail) { - error("missing observations in cov/cor"); + throw error("missing observations in cov/cor"); } else { ind.updateDataAt(i, 0, check); } @@ -736,8 +735,8 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 { } } - private static void error(String message) { - RError.error(NO_CALLER, Message.GENERIC, message); + private RuntimeException error(String message) { + throw error(Message.GENERIC, message); } private boolean checkNAs(double... xs) { diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cutree.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cutree.java index a2de828f383f45478803349ea5674253ff4a63f2..d4f616e70c5549f6e549c139b0dc12099410b1b5 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cutree.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cutree.java @@ -10,6 +10,9 @@ */ package com.oracle.truffle.r.library.stats; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyIntegerVector; + import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode; @@ -24,8 +27,8 @@ public abstract class Cutree extends RExternalBuiltinNode.Arg2 { static { Casts casts = new Casts(Cutree.class); - casts.arg(0).asIntegerVector(); - casts.arg(1).asIntegerVector(); + casts.arg(0).mustNotBeMissing().mapIf(nullValue(), emptyIntegerVector()).asIntegerVector(); + casts.arg(1).mustNotBeMissing().mapIf(nullValue(), emptyIntegerVector()).asIntegerVector(); } @Specialization diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java index 0eb3928748d7e3ef7d7e41770d2f85d9ffd5e668..9f35e9ded8df6ad2204d774c96389f66549ffc9d 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java @@ -10,10 +10,14 @@ */ package com.oracle.truffle.r.library.stats; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; + import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; @@ -21,7 +25,7 @@ public abstract class DoubleCentre extends RExternalBuiltinNode.Arg1 { static { Casts casts = new Casts(DoubleCentre.class); - casts.arg(0).asDoubleVector(); + casts.arg(0).mustBe(missingValue().not()).mustBe(nullValue().not(), RError.Message.MACRO_CAN_BE_APPLIED_TO, "REAL()", "numeric", "NULL").asDoubleVector(); } @Specialization diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java index c1ea604e1f543e23cfcc47a014e063141898a818..0379b9d46dfdf186173170d2d399bd36c5ce55f2 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java @@ -12,8 +12,10 @@ */ package com.oracle.truffle.r.library.stats; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notIntNA; -import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; import static com.oracle.truffle.r.runtime.RError.Message.NA_IN_PROB_VECTOR; import static com.oracle.truffle.r.runtime.RError.Message.NEGATIVE_PROBABILITY; import static com.oracle.truffle.r.runtime.RError.Message.NO_POSITIVE_PROBABILITIES; @@ -36,6 +38,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandomNumberProvider; import com.oracle.truffle.r.runtime.nmath.distr.RMultinom; import com.oracle.truffle.r.runtime.nmath.distr.Rbinom; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.rng.RRNG; /** @@ -50,9 +53,14 @@ public abstract class RMultinomNode extends RExternalBuiltinNode.Arg3 { static { Casts casts = new Casts(RMultinomNode.class); - casts.arg(0).asIntegerVector().findFirst().mustBe(notIntNA(), SHOW_CALLER, Message.INVALID_FIRST_ARGUMENT_NAME, "n"); - casts.arg(1).asIntegerVector().findFirst().mustBe(notIntNA(), SHOW_CALLER, Message.INVALID_SECOND_ARGUMENT_NAME, "size"); - casts.arg(2).asDoubleVector(); + casts.arg(0).asIntegerVector().findFirst().mustBe(notIntNA(), Message.INVALID_FIRST_ARGUMENT_NAME, "n"); + casts.arg(1).asIntegerVector().findFirst().mustBe(notIntNA(), Message.INVALID_SECOND_ARGUMENT_NAME, "size"); + casts.arg(2).mustBe(missingValue().not(), Message.ARGUMENT_MISSING, "prob").mapIf(nullValue(), emptyDoubleVector()).asDoubleVector(); + } + + @Override + protected RBaseNode getErrorContext() { + return RError.SHOW_CALLER; } @Specialization @@ -88,15 +96,15 @@ public abstract class RMultinomNode extends RExternalBuiltinNode.Arg3 { return resultVec; } - private static void fixupProb(double[] p) { + private void fixupProb(double[] p) { double sum = 0.0; int npos = 0; for (double prob : p) { if (!Double.isFinite(prob)) { - throw RError.error(SHOW_CALLER, NA_IN_PROB_VECTOR); + throw error(NA_IN_PROB_VECTOR); } if (prob < 0.0) { - throw RError.error(SHOW_CALLER, NEGATIVE_PROBABILITY); + throw error(NEGATIVE_PROBABILITY); } if (prob > 0.0) { npos++; @@ -104,7 +112,7 @@ public abstract class RMultinomNode extends RExternalBuiltinNode.Arg3 { } } if (npos == 0) { - throw RError.error(SHOW_CALLER, NO_POSITIVE_PROBABILITIES); + throw error(NO_POSITIVE_PROBABILITIES); } for (int i = 0; i < p.length; i++) { p[i] /= sum; diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java index 14f9409f3ec099c5a45cfb569c74874686ec38a2..a0792babded9bea59dbdce3bc98c75732dd23191 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java @@ -13,6 +13,8 @@ package com.oracle.truffle.r.library.stats; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue; import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; import static com.oracle.truffle.r.runtime.RError.Message.INVALID_UNNAMED_ARGUMENTS; @@ -22,7 +24,6 @@ import java.util.Arrays; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.LoopConditionProfile; @@ -30,7 +31,6 @@ import com.oracle.truffle.r.library.stats.RandFunctionsNodesFactory.ConvertToLen import com.oracle.truffle.r.library.stats.RandFunctionsNodesFactory.RandFunction1NodeGen; import com.oracle.truffle.r.library.stats.RandFunctionsNodesFactory.RandFunction2NodeGen; import com.oracle.truffle.r.library.stats.RandFunctionsNodesFactory.RandFunction3NodeGen; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.nodes.profile.VectorLengthProfile; @@ -76,7 +76,7 @@ public final class RandFunctionsNodes { public int lengthOne(RAbstractVector vector, @Cached("createNonPreserving()") CastIntegerNode castNode, @Cached("create()") BranchProfile seenNA) { - int result = ((RAbstractIntVector) castNode.execute(vector)).getDataAt(0); + int result = ((RAbstractIntVector) castNode.doCast(vector)).getDataAt(0); if (RRuntime.isNA(result) || result < 0) { seenNA.enter(); throw RError.error(SHOW_CALLER, INVALID_UNNAMED_ARGUMENTS); @@ -90,7 +90,7 @@ public final class RandFunctionsNodes { } private static void addLengthCast(Casts casts) { - casts.arg(0).defaultError(SHOW_CALLER, INVALID_UNNAMED_ARGUMENTS).mustBe(abstractVectorValue()).asVector(); + casts.arg(0).defaultError(INVALID_UNNAMED_ARGUMENTS).mustBe(abstractVectorValue()).asVector(); } } @@ -99,8 +99,7 @@ public final class RandFunctionsNodes { * result vector, and similar. The random function is provided as implementation of * {@link RandFunction3_Double}. */ - @TypeSystemReference(EmptyTypeSystemFlatLayout.class) - protected abstract static class RandFunctionExecutorBase extends Node { + protected abstract static class RandFunctionExecutorBase extends RBaseNode { static final class RandGenerationNodeData { final BranchProfile nanResult = BranchProfile.create(); final BranchProfile nan = BranchProfile.create(); @@ -112,6 +111,11 @@ public final class RandFunctionsNodes { } } + @Override + protected RBaseNode getErrorContext() { + return RError.SHOW_CALLER; + } + public abstract Object execute(RAbstractVector length, RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, RandomNumberProvider rand); @Child private ConvertToLength convertToLength = ConvertToLengthNodeGen.create(); @@ -150,12 +154,11 @@ public final class RandFunctionsNodes { RRNG.putRNGState(); } - static void showNAWarning() { - RError.warning(SHOW_CALLER, RError.Message.NA_PRODUCED); + void showNAWarning() { + warning(RError.Message.NA_PRODUCED); } } - @TypeSystemReference(EmptyTypeSystemFlatLayout.class) protected abstract static class RandFunctionIntExecutorNode extends RandFunctionExecutorBase { @Child private RandFunction3_Double function; @@ -201,7 +204,6 @@ public final class RandFunctionsNodes { } } - @TypeSystemReference(EmptyTypeSystemFlatLayout.class) protected abstract static class RandFunctionDoubleExecutorNode extends RandFunctionExecutorBase { @Child private RandFunction3_Double function; @@ -265,9 +267,9 @@ public final class RandFunctionsNodes { static { Casts casts = new Casts(RandFunction3Node.class); ConvertToLength.addLengthCast(casts); - casts.arg(1).asDoubleVector(); - casts.arg(2).asDoubleVector(); - casts.arg(3).asDoubleVector(); + casts.arg(1).mustBe(nullValue().not(), RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "a").asDoubleVector(); + casts.arg(2).mustBe(nullValue().not(), RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "b").asDoubleVector(); + casts.arg(3).mustBe(nullValue().not(), RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "c").asDoubleVector(); } @Specialization @@ -295,8 +297,8 @@ public final class RandFunctionsNodes { static { Casts casts = new Casts(RandFunction2Node.class); ConvertToLength.addLengthCast(casts); - casts.arg(1).asDoubleVector(); - casts.arg(2).asDoubleVector(); + casts.arg(1).mustBe(nullValue().not(), RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "a").asDoubleVector(); + casts.arg(2).mustBe(nullValue().not(), RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "b").asDoubleVector(); } @Specialization @@ -324,7 +326,7 @@ public final class RandFunctionsNodes { static { Casts casts = new Casts(RandFunction1Node.class); ConvertToLength.addLengthCast(casts); - casts.arg(1).asDoubleVector(); + casts.arg(1).mustBe(nullValue().not(), RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "a").asDoubleVector(); } @Specialization diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java index 03b79a3c255bd585bc26178647cadec00635bb40..2af07cc9e5d58828686678f3503daa476edb5c3a 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java @@ -11,22 +11,22 @@ */ package com.oracle.truffle.r.library.stats; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asIntegerVector; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.findFirst; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; -import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; -import com.oracle.truffle.r.runtime.RError; import static com.oracle.truffle.r.runtime.RError.Message.NA_INTRODUCED_COERCION; -import static com.oracle.truffle.r.runtime.RError.NO_CALLER; import static com.oracle.truffle.r.runtime.RRuntime.INT_NA; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RList; @@ -49,33 +49,54 @@ public class SplineFunctions { casts.arg(0).mapNull(constant(INT_NA)).mapIf(numericValue(), chain(asIntegerVector()).with(findFirst().integerElement(INT_NA)).end(), chain(asIntegerVector()).with(findFirst().integerElement(INT_NA)).with( - Predef.shouldBe(integerValue(), NO_CALLER, NA_INTRODUCED_COERCION)).end()); - casts.arg(1).allowMissing().asDoubleVector(); - casts.arg(2).allowMissing().asDoubleVector(); + Predef.shouldBe(integerValue(), NA_INTRODUCED_COERCION)).end()); + casts.arg(1).mustNotBeMissing().asDoubleVector(); + casts.arg(2).mustNotBeMissing().asDoubleVector(); } @Specialization @TruffleBoundary protected Object splineCoef(int method, RAbstractDoubleVector x, RAbstractDoubleVector y) { - return SplineFunctions.splineCoef(method, x.materialize(), y.materialize()); + return splineCoefImpl(method, x.materialize(), y.materialize()); } @Specialization @TruffleBoundary - protected Object splineCoef(int method, RAbstractDoubleVector x, RNull y) { - return SplineFunctions.splineCoef(method, x.materialize(), RDataFactory.createDoubleVector(0)); + protected Object splineCoef(int method, RAbstractDoubleVector x, @SuppressWarnings("unused") RNull y) { + return splineCoefImpl(method, x.materialize(), RDataFactory.createDoubleVector(0)); } @Specialization @TruffleBoundary - protected Object splineCoef(int method, RNull x, RAbstractDoubleVector y) { - return SplineFunctions.splineCoef(method, RDataFactory.createDoubleVector(0), y.materialize()); + protected Object splineCoef(int method, @SuppressWarnings("unused") RNull x, RAbstractDoubleVector y) { + return splineCoefImpl(method, RDataFactory.createDoubleVector(0), y.materialize()); } @Specialization @TruffleBoundary - protected Object splineCoef(int method, RNull x, RNull y) { - return SplineFunctions.splineCoef(method, RDataFactory.createDoubleVector(0), RDataFactory.createDoubleVector(0)); + protected Object splineCoef(int method, @SuppressWarnings("unused") RNull x, @SuppressWarnings("unused") RNull y) { + return splineCoefImpl(method, RDataFactory.createDoubleVector(0), RDataFactory.createDoubleVector(0)); + } + + private RList splineCoefImpl(int method, RDoubleVector x, RDoubleVector y) { + int n = x.getLength(); + if (y.getLength() != n) { + throw error(RError.Message.INPUTS_DIFFERENT_LENGTHS); + } + + double[] b = new double[n]; + double[] c = new double[n]; + double[] d = new double[n]; + + SplineFunctions.splineCoef(method, n, x.getDataWithoutCopying(), y.getDataWithoutCopying(), b, c, d); + + final boolean complete = x.isComplete() && y.isComplete(); + RDoubleVector bv = RDataFactory.createDoubleVector(b, complete); + RDoubleVector cv = RDataFactory.createDoubleVector(c, complete); + RDoubleVector dv = RDataFactory.createDoubleVector(d, complete); + Object[] resultData = new Object[]{method, n, x, y, bv, cv, dv}; + RStringVector resultNames = RDataFactory.createStringVector(new String[]{"method", "n", "x", "y", "b", "c", "d"}, RDataFactory.COMPLETE_VECTOR); + return RDataFactory.createList(resultData, resultNames); } } @@ -95,27 +116,6 @@ public class SplineFunctions { } } - private static RList splineCoef(int method, RDoubleVector x, RDoubleVector y) { - final int n = x.getLength(); - if (y.getLength() != n) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.INPUTS_DIFFERENT_LENGTHS); - } - - double[] b = new double[n]; - double[] c = new double[n]; - double[] d = new double[n]; - - splineCoef(method, n, x.getDataWithoutCopying(), y.getDataWithoutCopying(), b, c, d); - - final boolean complete = x.isComplete() && y.isComplete(); - RDoubleVector bv = RDataFactory.createDoubleVector(b, complete); - RDoubleVector cv = RDataFactory.createDoubleVector(c, complete); - RDoubleVector dv = RDataFactory.createDoubleVector(d, complete); - Object[] resultData = new Object[]{method, n, x, y, bv, cv, dv}; - RStringVector resultNames = RDataFactory.createStringVector(new String[]{"method", "n", "x", "y", "b", "c", "d"}, RDataFactory.COMPLETE_VECTOR); - return RDataFactory.createList(resultData, resultNames); - } - private static void splineCoef(int method, int n, double[] x, double[] y, double[] b, double[] c, double[] d) { switch (method) { case 1: diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java index 11a0662bdfafa8f80dd5bbb6728c4a0adbfc4c3f..ec765e5a52901a9f96ca97ee9c14af841a886072 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java @@ -12,6 +12,11 @@ */ package com.oracle.truffle.r.library.stats; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; @@ -30,9 +35,11 @@ import com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function3_2 import com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function4_1NodeGen; import com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function4_2NodeGen; import com.oracle.truffle.r.nodes.attributes.UnaryCopyAttributesNode; +import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.nodes.profile.VectorLengthProfile; 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.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDouble; @@ -137,6 +144,15 @@ public final class StatsFunctionsNodes { return resultVec; } + private static void castBoolean(Casts casts, int index, byte defaultValue) { + // defensively we map missing to the default values + casts.arg(index).asLogicalVector().findFirst(defaultValue).map(toBoolean()); + } + + private static void castDoubleVec(Casts casts, int index) { + casts.arg(index).mustBe(numericValue(), Message.NON_NUMERIC_MATH).asDoubleVector(); + } + public abstract static class Function3_2Node extends RExternalBuiltinNode.Arg5 { private final Function3_2 function; @@ -150,11 +166,11 @@ public final class StatsFunctionsNodes { static { Casts casts = new Casts(Function3_2Node.class); - casts.arg(0).asDoubleVector(); - casts.arg(1).asDoubleVector(); - casts.arg(2).asDoubleVector(); - casts.arg(3).asLogicalVector().findFirst().map(toBoolean()); - casts.arg(4).asLogicalVector().findFirst().map(toBoolean()); + castDoubleVec(casts, 0); + castDoubleVec(casts, 1); + castDoubleVec(casts, 2); + castBoolean(casts, 3, RRuntime.LOGICAL_TRUE); + castBoolean(casts, 4, RRuntime.LOGICAL_FALSE); } @Specialization @@ -178,11 +194,11 @@ public final class StatsFunctionsNodes { static { Casts casts = new Casts(Function4_1Node.class); - casts.arg(0).asDoubleVector(); - casts.arg(1).asDoubleVector(); - casts.arg(2).asDoubleVector(); - casts.arg(3).asDoubleVector(); - casts.arg(4).asLogicalVector().findFirst().map(toBoolean()); + castDoubleVec(casts, 0); + castDoubleVec(casts, 1); + castDoubleVec(casts, 2); + castDoubleVec(casts, 3); + castBoolean(casts, 4, RRuntime.LOGICAL_TRUE); } @Specialization @@ -206,12 +222,12 @@ public final class StatsFunctionsNodes { static { Casts casts = new Casts(Function4_2Node.class); - casts.arg(0).asDoubleVector(); - casts.arg(1).asDoubleVector(); - casts.arg(2).asDoubleVector(); - casts.arg(3).asDoubleVector(); - casts.arg(4).asLogicalVector().findFirst().map(toBoolean()); - casts.arg(5).asLogicalVector().findFirst().map(toBoolean()); + castDoubleVec(casts, 0); + castDoubleVec(casts, 1); + castDoubleVec(casts, 2); + castDoubleVec(casts, 3); + castBoolean(casts, 4, RRuntime.LOGICAL_TRUE); + castBoolean(casts, 5, RRuntime.LOGICAL_FALSE); } @Specialization @@ -235,10 +251,10 @@ public final class StatsFunctionsNodes { static { Casts casts = new Casts(Function3_1Node.class); - casts.arg(0).asDoubleVector(); - casts.arg(1).asDoubleVector(); - casts.arg(2).asDoubleVector(); - casts.arg(3).asLogicalVector().findFirst().map(toBoolean()); + castDoubleVec(casts, 0); + castDoubleVec(casts, 1); + castDoubleVec(casts, 2); + castBoolean(casts, 3, RRuntime.LOGICAL_TRUE); } @Specialization @@ -262,9 +278,9 @@ public final class StatsFunctionsNodes { static { Casts casts = new Casts(Function2_1Node.class); - casts.arg(0).asDoubleVector(); - casts.arg(1).asDoubleVector(); - casts.arg(2).asLogicalVector().findFirst().map(toBoolean()); + castDoubleVec(casts, 0); + castDoubleVec(casts, 1); + castBoolean(casts, 2, RRuntime.LOGICAL_TRUE); } @Specialization @@ -288,10 +304,10 @@ public final class StatsFunctionsNodes { static { Casts casts = new Casts(Function2_2Node.class); - casts.arg(0).asDoubleVector(); - casts.arg(1).asDoubleVector(); - casts.arg(2).asLogicalVector().findFirst().map(toBoolean()); - casts.arg(3).asLogicalVector().findFirst().map(toBoolean()); + castDoubleVec(casts, 0); + castDoubleVec(casts, 1); + castBoolean(casts, 2, RRuntime.LOGICAL_TRUE); + castBoolean(casts, 3, RRuntime.LOGICAL_FALSE); } @Specialization @@ -321,16 +337,16 @@ public final class StatsFunctionsNodes { break; case 2: if (!RRuntime.isFinite(f) || f < 0.0 || f > 1.0) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "approx(): invalid f value"); + throw error(RError.Message.GENERIC, "approx(): invalid f value"); } break; default: - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "approx(): invalid interpolation method"); + throw error(RError.Message.GENERIC, "approx(): invalid interpolation method"); } for (int i = 0; i < nx; i++) { if (RRuntime.isNAorNaN(x.getDataAt(i)) || RRuntime.isNAorNaN(y.getDataAt(i))) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, ("approx(): attempted to interpolate NA values")); + throw error(RError.Message.GENERIC, ("approx(): attempted to interpolate NA values")); } } @@ -347,7 +363,9 @@ public final class StatsFunctionsNodes { static { Casts casts = new Casts(Approx.class); - casts.arg(2).asDoubleVector(); + casts.arg(0).mustBe(instanceOf(RDoubleVector.class)); + casts.arg(1).mustBe(instanceOf(RDoubleVector.class)); + casts.arg(2).mustBe(missingValue().not()).mapIf(nullValue(), emptyDoubleVector()).asDoubleVector(); casts.arg(3).asIntegerVector().findFirst(); casts.arg(4).asDoubleVector().findFirst(); casts.arg(5).asDoubleVector().findFirst(); @@ -355,7 +373,7 @@ public final class StatsFunctionsNodes { } @Specialization - protected RDoubleVector approx(RDoubleVector x, RDoubleVector y, RDoubleVector v, int method, double yl, double yr, double f) { + protected RDoubleVector approx(RDoubleVector x, RDoubleVector y, RAbstractDoubleVector v, int method, double yl, double yr, double f) { int nx = x.getLength(); int nout = v.getLength(); double[] yout = new double[nout]; diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/D.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/D.java new file mode 100644 index 0000000000000000000000000000000000000000..f0d059510dfd53f75059882ad3365224b3d6d9dc --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/D.java @@ -0,0 +1,101 @@ +/* + * 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.stats.deriv; + +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.typeName; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.RASTUtils; +import com.oracle.truffle.r.nodes.access.ConstantNode; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RExpression; +import com.oracle.truffle.r.runtime.data.RLanguage; +import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; +import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor; + +public abstract class D extends RExternalBuiltinNode.Arg2 { + + static { + Casts casts = new Casts(D.class); + casts.arg(0, "expr").mustBe(instanceOf(RExpression.class).or(instanceOf(RLanguage.class)).or(instanceOf(RSymbol.class)).or(numericValue()).or(complexValue()), + RError.Message.INVALID_EXPRESSION_TYPE, typeName()); + casts.arg(1, "namevec").mustBe(stringValue()).asStringVector().mustBe(notEmpty(), RError.Message.GENERIC, "variable must be a character string").shouldBe(size(1), + RError.Message.ONLY_FIRST_VARIABLE_NAME).findFirst(); + } + + public static D create() { + return DNodeGen.create(); + } + + protected static boolean isConstant(Object expr) { + return !(expr instanceof RLanguage || expr instanceof RExpression || expr instanceof RSymbol); + } + + @Specialization(guards = "isConstant(expr)") + @TruffleBoundary + protected Object doD(Object expr, String var) { + return doD(ConstantNode.create(expr), var); + } + + @Specialization + @TruffleBoundary + protected Object doD(RSymbol expr, String var) { + return doD(RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, expr.getName(), false), var); + } + + @Specialization + @TruffleBoundary + protected Object doD(RLanguage expr, String var) { + return doD((RSyntaxElement) expr.getRep(), var); + } + + @Specialization + @TruffleBoundary + protected Object doD(RExpression expr, String var, + @Cached("create()") D dNode) { + if (expr.getLength() == 0) { + return RRuntime.DOUBLE_NA; + } + return dNode.execute(expr.getDataAt(0), var); + } + + private static Object doD(RSyntaxElement elem, String var) { + RSyntaxVisitor<RSyntaxElement> vis = new DerivVisitor(var); + RSyntaxElement dExpr = vis.accept(elem); + dExpr = Deriv.addParens(dExpr); + return RASTUtils.createLanguageElement(dExpr); + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java new file mode 100644 index 0000000000000000000000000000000000000000..d3dad0bc79bf3e3e0c56e7c91ab3d3e68a98f5f7 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java @@ -0,0 +1,736 @@ +/* + * 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) 1995, 1996 Robert Gentleman and Ross Ihaka + * Copyright (c) 1997-2013, The R Core Team + * Copyright (c) 2015, 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.stats.deriv; + +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asLogicalVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.boxPrimitive; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.findFirst; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lengthGte; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lengthLte; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.map; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.RootCallTarget; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.r.nodes.RRootNode; +import com.oracle.truffle.r.nodes.access.ConstantNode; +import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.nodes.function.FormalArguments; +import com.oracle.truffle.r.nodes.function.RCallSpecialNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RComplex; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.REmpty; +import com.oracle.truffle.r.runtime.data.RExpression; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RLanguage; +import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; +import com.oracle.truffle.r.runtime.nodes.RCodeBuilder; +import com.oracle.truffle.r.runtime.nodes.RCodeBuilder.Argument; +import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; +import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant; +import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; +import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction; +import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; +import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor; + +//Transcribed from GnuR, library/stats/src/deriv.c + +public abstract class Deriv extends RExternalBuiltinNode { + + static { + Casts casts = new Casts(Deriv.class); + casts.arg(1, "namevec").mustBe(stringValue()).asStringVector().mustBe(notEmpty(), RError.Message.INVALID_VARIABLE_NAMES); + casts.arg(2, "function.arg").mapIf(logicalValue(), chain(asLogicalVector()).with(findFirst().logicalElement()).with(map(toBoolean())).end()).mapIf(stringValue(), boxPrimitive()); + casts.arg(3, "tag").defaultError(RError.Message.INVALID_VARIABLE_NAMES).mustBe(stringValue()).asStringVector().mustBe(notEmpty()).findFirst().mustBe(lengthGte(1).and(lengthLte(60))); + casts.arg(4, "hessian").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean()); + } + + static final String LEFT_PAREN = "("; + static final String PLUS = "+"; + static final String MINUS = "-"; + static final String TIMES = "*"; + static final String DIVIDE = "/"; + static final String POWER = "^"; + static final String LOG = "log"; + static final String EXP = "exp"; + static final String COS = "cos"; + static final String SIN = "sin"; + static final String TAN = "tan"; + static final String COSH = "cosh"; + static final String SINH = "sinh"; + static final String TANH = "tanh"; + static final String SQRT = "sqrt"; + static final String PNORM = "pnorm"; + static final String DNORM = "dnorm"; + static final String ASIN = "asin"; + static final String ACOS = "acos"; + static final String ATAN = "atan"; + static final String GAMMA = "gamma"; + static final String LGAMMA = "lgamma"; + static final String DIGAMMA = "digamma"; + static final String TRIGAMMA = "trigamma"; + static final String PSIGAMMA = "psigamma"; + + public static Deriv create() { + return DerivNodeGen.create(); + } + + public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5); + + @Override + public Object call(VirtualFrame frame, RArgsValuesAndNames args) { + checkLength(args, 5); + return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4)); + } + + @Override + protected Object call(RArgsValuesAndNames args) { + throw RInternalError.shouldNotReachHere(); + } + + protected static boolean isConstant(Object expr) { + return !(expr instanceof RLanguage || expr instanceof RExpression || expr instanceof RSymbol); + } + + @Specialization(guards = "isConstant(expr)") + protected Object derive(VirtualFrame frame, Object expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) { + return derive(frame, RDataFactory.createLanguage(ConstantNode.create(expr)), names, functionArg, tag, hessian); + } + + @Specialization + protected Object derive(VirtualFrame frame, RSymbol expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) { + return derive(frame, (RBaseNode) RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, expr.getName(), false), names, functionArg, tag, hessian); + } + + @Specialization + protected Object derive(VirtualFrame frame, RExpression expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian, + @Cached("create()") Deriv derivNode) { + return derivNode.execute(frame, expr.getDataAt(0), names, functionArg, tag, hessian); + } + + @Specialization + protected Object derive(VirtualFrame frame, RLanguage expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) { + return derive(frame, expr.getRep(), names, functionArg, tag, hessian); + } + + private Object derive(VirtualFrame frame, RBaseNode elem, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) { + return findDerive(elem, names, functionArg, tag, hessian).getResult(frame); + } + + private static final class DerivResult { + private final RExpression result; + private final RSyntaxNode blockCall; + private final List<Argument<RSyntaxNode>> targetArgs; + + private DerivResult(RExpression result) { + this.result = result; + blockCall = null; + targetArgs = null; + } + + private DerivResult(RSyntaxNode blockCall, List<Argument<RSyntaxNode>> targetArgs) { + this.blockCall = blockCall; + this.targetArgs = targetArgs; + result = null; + } + + private Object getResult(VirtualFrame frame) { + if (result != null) { + return result; + } + RootCallTarget callTarget = getRootCallTarget(); + FrameSlotChangeMonitor.initializeEnclosingFrame(callTarget.getRootNode().getFrameDescriptor(), frame); + return RDataFactory.createFunction(RFunction.NO_NAME, RFunction.NO_NAME, callTarget, null, frame.materialize()); + } + + @TruffleBoundary + private RootCallTarget getRootCallTarget() { + return RContext.getASTBuilder().rootFunction(RSyntaxNode.LAZY_DEPARSE, targetArgs, blockCall, null); + } + } + + @TruffleBoundary + private DerivResult findDerive(RBaseNode elem, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) { + LinkedList<RSyntaxNode> exprlist = new LinkedList<>(); + int fIndex = findSubexpression(elem, exprlist, tag); + + int nderiv = names.getLength(); + int[] dIndex = new int[nderiv]; + int[] d2Index = hessian ? new int[(nderiv * (1 + nderiv)) / 2] : null; + for (int i = 0, k = 0; i < nderiv; i++) { + RBaseNode dExpr = d(elem, names.getDataAt(i)); + dIndex[i] = findSubexpression(dExpr, exprlist, tag); + + if (hessian) { + for (int j = i; j < nderiv; j++) { + RBaseNode d2Expr = d(dExpr, names.getDataAt(j)); + d2Index[k] = findSubexpression(d2Expr, exprlist, tag); + k++; + } + } + } + + int nexpr = exprlist.size(); + + if (fIndex > 0) { + exprlist.add(ReadVariableNode.create(tag + fIndex)); + } else { + exprlist.add(cloneElement(elem.asRSyntaxNode())); + } + + exprlist.add(null); + if (hessian) { + exprlist.add(null); + } + + for (int i = 0, k = 0; i < nderiv; i++) { + if (dIndex[i] > 0) { + exprlist.add(ReadVariableNode.create(tag + dIndex[i])); + + if (hessian) { + RBaseNode dExpr = d(elem, names.getDataAt(i)); + for (int j = i; j < nderiv; j++) { + if (d2Index[k] > 0) { + exprlist.add(ReadVariableNode.create(tag + d2Index[k])); + } else { + exprlist.add((RSyntaxNode) d(dExpr, names.getDataAt(j))); + } + k++; + } + } + + } else { + // the first derivative is constant or simple variable + // TODO: do not call the d twice + RBaseNode dExpr = d(elem, names.getDataAt(i)); + exprlist.add((RSyntaxNode) dExpr); + + if (hessian) { + for (int j = i; j < nderiv; j++) { + if (d2Index[k] > 0) { + exprlist.add(ReadVariableNode.create(tag + d2Index[k])); + } else { + RBaseNode d2Expr = d(dExpr, names.getDataAt(j)); + if (isZero((RSyntaxElement) d2Expr)) { + exprlist.add(null); + } else { + exprlist.add((RSyntaxNode) d2Expr); + } + } + k++; + } + } + } + } + + exprlist.add(null); + exprlist.add(null); + if (hessian) { + exprlist.add(null); + } + + for (int i = 0; i < nexpr; i++) { + String subexprName = tag + (i + 1); + if (countOccurences(subexprName, exprlist, i + 1) < 2) { + replace(subexprName, exprlist.get(i), exprlist, i + 1); + exprlist.set(i, null); + } else { + exprlist.set(i, createAssignNode(subexprName, exprlist.get(i))); + } + } + + int p = nexpr; + exprlist.set(p++, createAssignNode(".value", exprlist.get(nexpr))); // .value <- + exprlist.set(p++, createGrad(names)); // .grad <- + if (hessian) { + exprlist.set(p++, createHess(names)); // .hessian + } + // .grad[, "..."] <- ... + for (int i = 0; i < nderiv; i++) { + RSyntaxNode ans = exprlist.get(p); + exprlist.set(p, derivAssign(names.getDataAt(i), ans)); + p++; + + if (hessian) { + for (int j = i; j < nderiv; j++, p++) { + ans = exprlist.get(p); + if (ans != null) { + if (i == j) { + exprlist.set(p, hessAssign1(names.getDataAt(i), addParens(ans))); + } else { + exprlist.set(p, hessAssign2(names.getDataAt(i), names.getDataAt(j), addParens(ans))); + } + } + } + } + + } + // attr(.value, "gradient") <- .grad + exprlist.set(p++, addGrad()); + if (hessian) { + exprlist.set(p++, addHess()); + } + + // .value + exprlist.set(p++, ReadVariableNode.create(".value")); + + // prune exprlist + exprlist.removeAll(Collections.singleton(null)); + + List<Argument<RSyntaxNode>> blockStatements = new ArrayList<>(exprlist.size()); + for (RSyntaxNode e : exprlist) { + blockStatements.add(RCodeBuilder.argument(e)); + } + RSyntaxNode blockCall = RContext.getASTBuilder().call(RSyntaxNode.LAZY_DEPARSE, ReadVariableNode.create("{"), blockStatements); + + if (functionArg instanceof RAbstractStringVector) { + RAbstractStringVector funArgNames = (RAbstractStringVector) functionArg; + List<Argument<RSyntaxNode>> targetArgs = new ArrayList<>(); + for (int i = 0; i < funArgNames.getLength(); i++) { + targetArgs.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, funArgNames.getDataAt(i), ConstantNode.create(RMissing.instance))); + } + + return new DerivResult(blockCall, targetArgs); + } else if (functionArg == Boolean.TRUE) { + List<Argument<RSyntaxNode>> targetArgs = new ArrayList<>(); + for (int i = 0; i < names.getLength(); i++) { + targetArgs.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, names.getDataAt(i), ConstantNode.create(RMissing.instance))); + } + + return new DerivResult(blockCall, targetArgs); + } else if (functionArg instanceof RFunction) { + RFunction funTemplate = (RFunction) functionArg; + FormalArguments formals = ((RRootNode) funTemplate.getRootNode()).getFormalArguments(); + RNode[] defArgs = formals.getArguments(); + List<Argument<RSyntaxNode>> targetArgs = new ArrayList<>(); + for (int i = 0; i < defArgs.length; i++) { + targetArgs.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, formals.getSignature().getName(i), cloneElement((RSyntaxNode) defArgs[i]))); + } + + return new DerivResult(blockCall, targetArgs); + } else { + RLanguage lan = RDataFactory.createLanguage(blockCall.asRNode()); + RExpression res = RDataFactory.createExpression(new Object[]{lan}); + return new DerivResult(res); + } + + } + + private int findSubexpression(RBaseNode expr, List<RSyntaxNode> exprlist, String tag) { + if (!(expr instanceof RSyntaxElement)) { + throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "FindSubexprs"); + } + + RSyntaxVisitor<Integer> vis = new RSyntaxVisitor<Integer>() { + @Override + protected Integer visit(RSyntaxCall call) { + if (call.getSyntaxLHS() instanceof RSyntaxLookup && ((RSyntaxLookup) call.getSyntaxLHS()).getIdentifier() == LEFT_PAREN) { + return accept(call.getSyntaxArguments()[0]); + } + + RSyntaxElement[] args = call.getSyntaxArguments(); + List<Argument<RSyntaxNode>> newArgs = new ArrayList<>(); + for (int i = 0; i < args.length; i++) { + int k = accept(args[i]); + if (k > 0) { + newArgs.add(RCodeBuilder.argument(ReadVariableNode.create(tag + k))); + } else { + newArgs.add(RCodeBuilder.argument(cloneElement(args[i]))); + } + } + RSyntaxNode newCall = RContext.getASTBuilder().call(call.getSourceSection(), cloneElement(call.getSyntaxLHS()), newArgs); + return accumulate(newCall, exprlist); + } + + @Override + protected Integer visit(RSyntaxConstant element) { + return checkConstant(element.getValue()); + } + + @Override + protected Integer visit(RSyntaxLookup element) { + return 0; + } + + @Override + protected Integer visit(RSyntaxFunction element) { + throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "FindSubexprs"); + } + + }; + return vis.accept((RSyntaxElement) expr); + } + + private static int checkConstant(Object val) { + if (val instanceof Double || val instanceof Integer || val instanceof RComplex || val instanceof Byte || val instanceof RSymbol) { + return 0; + } else { + throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "FindSubexprs"); + } + } + + private static boolean isDoubleValue(RSyntaxElement elem, double value) { + if (elem instanceof RSyntaxConstant) { + Object val = ((RSyntaxConstant) elem).getValue(); + if (val instanceof Number) { + return ((Number) val).doubleValue() == value; + } else { + return false; + } + } else { + return false; + } + } + + static boolean isZero(RSyntaxElement elem) { + return isDoubleValue(elem, 0.); + } + + static boolean isOne(RSyntaxElement elem) { + return isDoubleValue(elem, 1.); + } + + private int accumulate(RSyntaxElement expr, List<RSyntaxNode> exprlist) { + for (int k = 0; k < exprlist.size(); k++) { + if (equal(expr, exprlist.get(k))) { + return k + 1; + } + } + exprlist.add((RSyntaxNode) expr); + return exprlist.size(); + } + + // TODO: move to a utility class + private boolean equal(RSyntaxElement expr1, RSyntaxElement expr2) { + if (expr1.getClass() != expr2.getClass()) { + return false; + } + if (expr1 instanceof RSyntaxLookup) { + return ((RSyntaxLookup) expr1).getIdentifier() == ((RSyntaxLookup) expr2).getIdentifier(); + } + if (expr1 instanceof RSyntaxConstant) { + return ((RSyntaxConstant) expr1).getValue().equals(((RSyntaxConstant) expr2).getValue()); + } + if (expr1 instanceof RSyntaxCall) { + RSyntaxElement[] args1 = ((RSyntaxCall) expr1).getSyntaxArguments(); + RSyntaxElement[] args2 = ((RSyntaxCall) expr2).getSyntaxArguments(); + if (args1.length != args2.length) { + return false; + } + if (!equal(((RSyntaxCall) expr1).getSyntaxLHS(), ((RSyntaxCall) expr2).getSyntaxLHS())) { + return false; + } + for (int i = 0; i < args1.length; i++) { + if (!equal(args1[i], args2[i])) { + return false; + } + } + return true; + } + + throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "equal"); + } + + static String getFunctionName(RSyntaxElement expr) { + if (expr instanceof RSyntaxCall) { + RSyntaxCall call = (RSyntaxCall) expr; + return call.getSyntaxLHS() instanceof RSyntaxLookup ? ((RSyntaxLookup) call.getSyntaxLHS()).getIdentifier() : null; + } else { + return null; + } + } + + static RSyntaxNode cloneElement(RSyntaxElement element) { + return RContext.getASTBuilder().process(element); + } + + private static RBaseNode d(RBaseNode expr, String var) { + if (!(expr instanceof RSyntaxElement)) { + throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "FindSubexprs"); + } + + RSyntaxVisitor<RSyntaxElement> vis = new DerivVisitor(var); + return (RBaseNode) vis.accept((RSyntaxElement) expr); + } + + private static int argsLength(RSyntaxElement elem) { + if (elem instanceof RSyntaxCall) { + return ((RSyntaxCall) elem).getSyntaxArguments().length; + } else { + return 0; + } + } + + static RSyntaxElement arg(RSyntaxElement elem, int argIndex) { + assert elem instanceof RSyntaxCall && (argIndex < ((RSyntaxCall) elem).getSyntaxArguments().length); + return ((RSyntaxCall) elem).getSyntaxArguments()[argIndex]; + } + + private static RSyntaxElement setArg(RSyntaxElement elem, int argIndex, RSyntaxElement arg) { + assert elem instanceof RSyntaxCall && (argIndex < ((RSyntaxCall) elem).getSyntaxArguments().length); + RSyntaxCall call = (RSyntaxCall) elem; + RSyntaxElement[] args = call.getSyntaxArguments(); + RSyntaxNode[] newArgs = new RSyntaxNode[args.length]; + for (int i = 0; i < args.length; i++) { + if (i == argIndex) { + newArgs[i] = (RSyntaxNode) arg; + } else { + newArgs[i] = cloneElement(args[i]); + } + } + return RCallSpecialNode.createCall(call.getSourceSection(), (RNode) cloneElement(call.getSyntaxLHS()), ArgumentsSignature.empty(args.length), newArgs); + } + + static RSyntaxNode newCall(String functionName, RSyntaxElement arg1, RSyntaxElement arg2) { + if (arg2 == null) { + return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create(functionName), (RSyntaxNode) arg1); + } else { + return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create(functionName), (RSyntaxNode) arg1, (RSyntaxNode) arg2); + } + } + + private static int countOccurences(String subexprName, List<RSyntaxNode> exprlist, int fromIndex) { + if (fromIndex >= exprlist.size()) { + return 0; + } + + RSyntaxNode exprListNode = exprlist.get(fromIndex); + if (exprListNode == null) { + return countOccurences(subexprName, exprlist, fromIndex + 1); + } + + RSyntaxVisitor<Integer> vis = new RSyntaxVisitor<Integer>() { + @Override + protected Integer visit(RSyntaxCall element) { + RSyntaxElement[] args = element.getSyntaxArguments(); + int cnt = 0; + for (int i = 0; i < args.length; i++) { + cnt += accept(args[i]); + } + return cnt; + } + + @Override + protected Integer visit(RSyntaxConstant element) { + return 0; + } + + @Override + protected Integer visit(RSyntaxLookup element) { + return subexprName.equals(element.getIdentifier()) ? 1 : 0; + } + + @Override + protected Integer visit(RSyntaxFunction element) { + throw RInternalError.shouldNotReachHere(); + } + }; + + return vis.accept(exprListNode) + countOccurences(subexprName, exprlist, fromIndex + 1); + } + + private static void replace(String subexprName, RSyntaxNode replacement, List<RSyntaxNode> exprlist, int fromIndex) { + if (fromIndex >= exprlist.size()) { + return; + } + + RSyntaxElement exprListNode = exprlist.get(fromIndex); + if (exprListNode == null) { + replace(subexprName, replacement, exprlist, fromIndex + 1); + return; + } + + RSyntaxVisitor<RSyntaxElement> vis = new RSyntaxVisitor<RSyntaxElement>() { + + // TODO: do not create a new call node after the first replacement + + @Override + protected RSyntaxElement visit(RSyntaxCall call) { + RSyntaxElement[] args = call.getSyntaxArguments(); + RSyntaxNode[] newArgs = new RSyntaxNode[args.length]; + for (int i = 0; i < args.length; i++) { + newArgs[i] = (RSyntaxNode) accept(args[i]); + } + return RCallSpecialNode.createCall(call.getSourceSection(), (RNode) call.getSyntaxLHS(), ArgumentsSignature.empty(args.length), newArgs); + } + + @Override + protected RSyntaxElement visit(RSyntaxConstant element) { + return element; + } + + @Override + protected RSyntaxElement visit(RSyntaxLookup element) { + return subexprName.equals(element.getIdentifier()) ? replacement : element; + } + + @Override + protected RSyntaxElement visit(RSyntaxFunction element) { + throw RInternalError.shouldNotReachHere(); + } + + }; + + exprlist.set(fromIndex, (RSyntaxNode) vis.accept(exprListNode)); + + replace(subexprName, replacement, exprlist, fromIndex + 1); + } + + private static RSyntaxNode createAssignNode(String varName, RSyntaxNode rhs) { + return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), ReadVariableNode.create(varName.intern()), addParens(rhs)); + } + + private static RSyntaxNode hessAssign1(String varName, RSyntaxNode rhs) { + RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("["), ReadVariableNode.create(".hessian"), ConstantNode.create(REmpty.instance), + ConstantNode.create(varName.intern()), ConstantNode.create(varName.intern())); + return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp, rhs); + } + + private static RSyntaxNode hessAssign2(String varName1, String varName2, RSyntaxNode rhs) { + RSyntaxNode tmp1 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("["), ReadVariableNode.create(".hessian"), ConstantNode.create(REmpty.instance), + ConstantNode.create(varName1.intern()), ConstantNode.create(varName2.intern())); + RSyntaxNode tmp2 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("["), ReadVariableNode.create(".hessian"), ConstantNode.create(REmpty.instance), + ConstantNode.create(varName2.intern()), ConstantNode.create(varName1.intern())); + + RSyntaxNode tmp3 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp2, rhs); + return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp1, tmp3); + } + + private static RSyntaxNode createGrad(RAbstractStringVector names) { + int n = names.getLength(); + List<Argument<RSyntaxNode>> cArgs = new ArrayList<>(); + for (int i = 0; i < n; i++) { + cArgs.add(RCodeBuilder.argument(ConstantNode.create(names.getDataAt(i).intern()))); + } + RSyntaxNode tmp1 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("c"), cArgs); + RSyntaxNode dimnames = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("list"), ConstantNode.create(RNull.instance), tmp1); + + RSyntaxNode tmp2 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("length"), ReadVariableNode.create(".value")); + RSyntaxNode dim = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("c"), tmp2, ConstantNode.create(n)); + ConstantNode data = ConstantNode.create(0.); + + RSyntaxNode p = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("array"), data, dim, dimnames); + return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), ReadVariableNode.create(".grad"), p); + } + + private static RSyntaxNode createHess(RAbstractStringVector names) { + int n = names.getLength(); + List<Argument<RSyntaxNode>> cArgs = new ArrayList<>(); + for (int i = 0; i < n; i++) { + cArgs.add(RCodeBuilder.argument(ConstantNode.create(names.getDataAt(i).intern()))); + } + RSyntaxNode tmp1 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("c"), cArgs); + RSyntaxNode tmp1Clone = cloneElement(tmp1); + RSyntaxNode dimnames = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("list"), ConstantNode.create(RNull.instance), tmp1, tmp1Clone); + + RSyntaxNode tmp2 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("length"), ReadVariableNode.create(".value")); + RSyntaxNode dim = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("c"), tmp2, ConstantNode.create(n), ConstantNode.create(n)); + ConstantNode data = ConstantNode.create(0.); + + RSyntaxNode p = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("array"), data, dim, dimnames); + return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), ReadVariableNode.create(".hessian"), p); + } + + private static RSyntaxNode derivAssign(String name, RSyntaxNode expr) { + RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("["), ReadVariableNode.create(".grad"), ConstantNode.create(REmpty.instance), + ConstantNode.create(name.intern())); + return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp, expr); + } + + private static RSyntaxNode addGrad() { + RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("attr"), ReadVariableNode.create(".value"), ConstantNode.create("gradient")); + return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp, ReadVariableNode.create(".grad")); + } + + private static RSyntaxNode addHess() { + RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("attr"), ReadVariableNode.create(".value"), ConstantNode.create("hessian")); + return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp, ReadVariableNode.create(".hessian")); + } + + private static boolean isForm(RSyntaxElement expr, String functionName) { + return argsLength(expr) == 2 && getFunctionName(expr) == functionName; + } + + static RSyntaxNode addParens(RSyntaxElement node) { + RSyntaxElement expr = node; + if (node instanceof RSyntaxCall) { + RSyntaxCall call = (RSyntaxCall) node; + RSyntaxElement[] args = call.getSyntaxArguments(); + RSyntaxNode[] newArgs = new RSyntaxNode[args.length]; + for (int i = 0; i < args.length; i++) { + newArgs[i] = addParens(args[i]); + } + expr = RCallSpecialNode.createCall(call.getSourceSection(), (RNode) cloneElement(call.getSyntaxLHS()), ArgumentsSignature.empty(args.length), newArgs); + } + + if (isForm(expr, PLUS)) { + if (isForm(arg(expr, 1), PLUS)) { + expr = setArg(expr, 1, newCall(LEFT_PAREN, arg(expr, 1), null)); + } + } else if (isForm(expr, MINUS)) { + if (isForm(arg(expr, 1), PLUS) || isForm(arg(expr, 1), MINUS)) { + expr = setArg(expr, 1, newCall(LEFT_PAREN, arg(expr, 1), null)); + } + } else if (isForm(expr, TIMES)) { + if (isForm(arg(expr, 1), PLUS) || isForm(arg(expr, 1), MINUS) || isForm(arg(expr, 1), TIMES) || + isForm(arg(expr, 1), DIVIDE)) { + expr = setArg(expr, 1, newCall(LEFT_PAREN, arg(expr, 1), null)); + } + if (isForm(arg(expr, 0), MINUS) || isForm(arg(expr, 0), MINUS)) { + expr = setArg(expr, 0, newCall(LEFT_PAREN, arg(expr, 0), null)); + } + } else if (isForm(expr, DIVIDE)) { + if (isForm(arg(expr, 1), PLUS) || isForm(arg(expr, 1), MINUS) || isForm(arg(expr, 1), TIMES) || + isForm(arg(expr, 1), DIVIDE)) { + expr = setArg(expr, 1, newCall(LEFT_PAREN, arg(expr, 1), null)); + } + if (isForm(arg(expr, 0), PLUS) || isForm(arg(expr, 0), MINUS)) { + expr = setArg(expr, 0, newCall(LEFT_PAREN, arg(expr, 0), null)); + } + } else if (isForm(expr, POWER)) { + if (isForm(arg(expr, 0), POWER)) { + expr = setArg(expr, 0, newCall(LEFT_PAREN, arg(expr, 0), null)); + } + if (isForm(arg(expr, 1), PLUS) || isForm(arg(expr, 1), MINUS) || isForm(arg(expr, 1), TIMES) || + isForm(arg(expr, 1), DIVIDE)) { + expr = setArg(expr, 1, newCall(LEFT_PAREN, arg(expr, 1), null)); + } + } + return (RSyntaxNode) expr; + } +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java new file mode 100644 index 0000000000000000000000000000000000000000..8dc3708ecd3527565a524513b83072f1e4407a53 --- /dev/null +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java @@ -0,0 +1,408 @@ +/* + * 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) 1995, 1996 Robert Gentleman and Ross Ihaka + * Copyright (c) 1997-2013, The R Core Team + * Copyright (c) 2015, 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.library.stats.deriv; + +import static com.oracle.truffle.r.library.stats.deriv.Deriv.*; + +import com.oracle.truffle.r.nodes.access.ConstantNode; +import com.oracle.truffle.r.runtime.RDeparse; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.Utils; +import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; +import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant; +import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; +import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction; +import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; +import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor; + +//Transcribed from GnuR, library/stats/src/deriv.c + +public class DerivVisitor extends RSyntaxVisitor<RSyntaxElement> { + + private final String var; + + DerivVisitor(String var) { + this.var = var; + } + + @Override + protected RSyntaxElement visit(RSyntaxCall call) { + String functionName = getFunctionName(call); + assert Utils.isInterned(functionName); + + RSyntaxElement arg0 = call.getSyntaxArguments()[0]; + RSyntaxElement arg1 = call.getSyntaxArguments().length > 1 ? call.getSyntaxArguments()[1] : null; + + if (functionName == LEFT_PAREN) { + return accept(arg0); + } + + if (functionName == PLUS) { + if (call.getSyntaxArguments().length == 1) { + return accept(arg0); + } else { + return simplify(PLUS, accept(arg0), accept(arg1)); + } + } + + if (functionName == MINUS) { + if (call.getSyntaxArguments().length == 1) { + return simplify(MINUS, accept(arg0), null); + } else { + return simplify(MINUS, accept(arg0), accept(arg1)); + } + } + + if (functionName == TIMES) { + return simplify(PLUS, simplify(TIMES, accept(arg0), cloneElement(arg1)), + simplify(TIMES, cloneElement(arg0), accept(arg1))); + } + + if (functionName == DIVIDE) { + return simplify(MINUS, + simplify(DIVIDE, accept(arg0), cloneElement(arg1)), + simplify(DIVIDE, + simplify(TIMES, cloneElement(arg0), accept(arg1)), + simplify(POWER, cloneElement(arg1), ConstantNode.create(2.)))); + } + + if (functionName == POWER) { + if (isNumeric(arg1)) { + return simplify(TIMES, + arg1, + simplify(TIMES, + accept(arg0), + simplify(POWER, cloneElement(arg0), decDouble(arg1)))); + + } else { + // (a^b)' = a^(b-1).b.a' + a^b.log(a).b' + RSyntaxElement expr1 = simplify(TIMES, + simplify(POWER, + arg0, + simplify(MINUS, cloneElement(arg1), ConstantNode.create(1.))), + simplify(TIMES, cloneElement(arg1), accept(arg0))); + + RSyntaxElement expr2 = simplify(TIMES, + simplify(POWER, cloneElement(arg0), cloneElement(arg1)), + simplify(TIMES, + simplify(LOG, cloneElement(arg0), null), + accept(arg1))); + return simplify(PLUS, expr1, expr2); + } + } + + if (functionName == EXP) { + return simplify(TIMES, cloneElement(call), accept(arg0)); + } + + if (functionName == LOG) { + if (call.getSyntaxArguments().length != 1) { + throw RError.error(RError.SHOW_CALLER, RError.Message.GENERIC, "only single-argument calls are supported"); + } + return simplify(DIVIDE, accept(arg0), cloneElement(arg0)); + } + + if (functionName == COS) { + return simplify(TIMES, + simplify(SIN, cloneElement(arg0), null), + simplify(MINUS, accept(arg0), null)); + } + + if (functionName == SIN) { + return simplify(TIMES, + simplify(COS, cloneElement(arg0), null), + accept(arg0)); + } + + if (functionName == TAN) { + return simplify(DIVIDE, + accept(arg0), + simplify(POWER, + simplify(COS, cloneElement(arg0), null), + ConstantNode.create(2.))); + } + + if (functionName == COSH) { + return simplify(TIMES, + simplify(SINH, cloneElement(arg0), null), + accept(arg0)); + } + + if (functionName == SINH) { + return simplify(TIMES, + simplify(COSH, cloneElement(arg0), null), + accept(arg0)); + } + + if (functionName == TANH) { + return simplify(DIVIDE, + accept(arg0), + simplify(POWER, + simplify(COSH, cloneElement(arg0), null), + ConstantNode.create(2.))); + } + + if (functionName == SQRT) { + return accept(simplify(POWER, cloneElement(arg0), ConstantNode.create(0.5))); + } + + if (functionName == PNORM) { + return simplify(TIMES, + simplify(DNORM, cloneElement(arg0), null), + accept(arg0)); + } + + if (functionName == DNORM) { + return simplify(TIMES, + simplify(MINUS, cloneElement(arg0), null), + simplify(TIMES, + simplify(DNORM, cloneElement(arg0), null), + accept(arg0))); + } + + if (functionName == ASIN) { + return simplify(DIVIDE, + accept(arg0), + simplify(SQRT, + simplify(MINUS, + ConstantNode.create(1.), + simplify(POWER, cloneElement(arg0), ConstantNode.create(2.))), + null)); + } + + if (functionName == ACOS) { + return simplify(MINUS, + simplify(DIVIDE, + accept(arg0), + simplify(SQRT, + simplify(MINUS, + ConstantNode.create(1.), + simplify(POWER, cloneElement(arg0), ConstantNode.create(2.))), + null)), + null); + } + + if (functionName == ATAN) { + return simplify(DIVIDE, + accept(arg0), + simplify(PLUS, + ConstantNode.create(1.), + simplify(POWER, cloneElement(arg0), ConstantNode.create(2.)))); + } + + if (functionName == LGAMMA) { + return simplify(TIMES, + accept(arg0), + simplify(DIGAMMA, cloneElement(arg0), null)); + } + + if (functionName == GAMMA) { + return simplify(TIMES, + accept(arg0), + simplify(TIMES, cloneElement(call), + simplify(DIGAMMA, cloneElement(arg0), null))); + } + + if (functionName == DIGAMMA) { + return simplify(TIMES, + accept(arg0), + simplify(TRIGAMMA, cloneElement(arg0), null)); + } + + if (functionName == TRIGAMMA) { + return simplify(TIMES, + accept(arg0), + simplify(PSIGAMMA, cloneElement(arg0), ConstantNode.create(2))); + } + + if (functionName == PSIGAMMA) { + if (call.getSyntaxArguments().length == 1) { + return simplify(TIMES, + accept(arg0), + simplify(PSIGAMMA, cloneElement(arg0), ConstantNode.create(1))); + } else if (isIntegerOrDouble(arg1)) { + return simplify(TIMES, + accept(arg0), + simplify(PSIGAMMA, cloneElement(arg0), incInteger(arg1))); + } else { + return simplify(TIMES, + accept(arg0), + simplify(PSIGAMMA, + cloneElement(arg0), + simplify(PLUS, cloneElement(arg1), ConstantNode.create(1)))); + } + } + + throw RError.error(RError.SHOW_CALLER, RError.Message.NOT_IN_DERIVATIVE_TABLE, RDeparse.deparseSyntaxElement(call.getSyntaxLHS())); + } + + @Override + protected RSyntaxElement visit(RSyntaxConstant element) { + return ConstantNode.create(0.); + } + + @Override + protected RSyntaxElement visit(RSyntaxLookup element) { + double dVal = element.getIdentifier().equals(var) ? 1 : 0; + return ConstantNode.create(dVal); + } + + @Override + protected RSyntaxElement visit(RSyntaxFunction element) { + throw RInternalError.shouldNotReachHere(); + } + + private RSyntaxElement simplify(String functionName, RSyntaxElement arg1, RSyntaxElement arg2) { + if (functionName == PLUS) { + if (arg2 == null) { + return arg1; + } else if (isZero(arg1)) { + return arg2; + } else if (isZero(arg2)) { + return arg1; + } else if (isUminus(arg1)) { + return simplify(MINUS, arg2, arg(arg1, 0)); + } else if (isUminus(arg2)) { + return simplify(MINUS, arg1, arg(arg2, 0)); + } else { + return newCall(PLUS, arg1, arg2); + } + } else if (functionName == MINUS) { + if (arg2 == null) { + if (isZero(arg1)) { + return ConstantNode.create(0.); + } else if (isUminus(arg1)) { + return arg(arg1, 0); + } else { + return newCall(MINUS, arg1, arg2); + } + } else { + if (isZero(arg2)) { + return arg1; + } else if (isZero(arg1)) { + return simplify(MINUS, arg2, null); + } else if (isUminus(arg1)) { + return simplify(MINUS, + simplify(PLUS, arg(arg1, 0), arg2), + null); + } else if (isUminus(arg2)) { + return simplify(PLUS, arg1, arg(arg2, 0)); + } else { + return newCall(MINUS, arg1, arg2); + } + } + } else if (functionName == TIMES) { + if (isZero(arg1) || isZero(arg2)) { + return ConstantNode.create(0.); + } else if (isOne(arg1)) { + return arg2; + } else if (isOne(arg2)) { + return arg1; + } else if (isUminus(arg1)) { + return simplify(MINUS, simplify(TIMES, arg(arg1, 0), arg2), null); + } else if (isUminus(arg2)) { + return simplify(MINUS, simplify(TIMES, arg1, arg(arg2, 0)), null); + } else { + return newCall(TIMES, arg1, arg2); + } + } else if (functionName == DIVIDE) { + if (isZero(arg1)) { + return ConstantNode.create(0.); + } else if (isZero(arg2)) { + return ConstantNode.create(RRuntime.DOUBLE_NA); + } else if (isOne(arg2)) { + return arg1; + } else if (isUminus(arg1)) { + return simplify(MINUS, simplify(DIVIDE, arg(arg1, 0), arg2), null); + } else if (isUminus(arg2)) { + return simplify(MINUS, simplify(DIVIDE, arg1, arg(arg2, 0)), null); + } else { + return newCall(DIVIDE, arg1, arg2); + } + } else if (functionName == POWER) { + if (isZero(arg2)) { + return ConstantNode.create(1.); + } else if (isZero(arg1)) { + return ConstantNode.create(0.); + } else if (isOne(arg1)) { + return ConstantNode.create(1.); + } else if (isOne(arg2)) { + return arg1; + } else { + return newCall(POWER, arg1, arg2); + } + } else if (functionName == EXP) { + // FIXME: simplify exp(lgamma( E )) = gamma( E ) + return newCall(EXP, arg1, null); + } else if (functionName == LOG) { + // FIXME: simplify log(gamma( E )) = lgamma( E ) + return newCall(LOG, arg1, null); + } else if (functionName == COS || functionName == SIN || functionName == TAN || functionName == COSH || functionName == SINH || functionName == TANH || functionName == SQRT || + functionName == PNORM || functionName == DNORM || functionName == ASIN || functionName == ACOS || functionName == ATAN || functionName == GAMMA || functionName == LGAMMA || + functionName == DIGAMMA || functionName == TRIGAMMA || functionName == PSIGAMMA) { + return newCall(functionName, arg1, arg2); + } else { + return ConstantNode.create(RRuntime.DOUBLE_NA); + } + } + + private static boolean isIntegerOrDouble(RSyntaxElement elem) { + if (elem instanceof RSyntaxConstant) { + Object val = ((RSyntaxConstant) elem).getValue(); + return val instanceof Integer || val instanceof Double; + } else { + return false; + } + } + + private static boolean isUminus(RSyntaxElement elem) { + if (elem instanceof RSyntaxCall && MINUS == getFunctionName(elem)) { + RSyntaxElement[] args = ((RSyntaxCall) elem).getSyntaxArguments(); + switch (args.length) { + case 1: + return true; + case 2: + return false; + default: + throw RError.error(RError.SHOW_CALLER, RError.Message.GENERIC, "invalid form in unary minus check"); + } + } else { + return false; + } + } + + private static boolean isNumeric(RSyntaxElement elem) { + if (elem instanceof RSyntaxConstant) { + Object val = ((RSyntaxConstant) elem).getValue(); + return val instanceof Integer || val instanceof Double || val instanceof Byte; + } else { + return false; + } + } + + private static RSyntaxConstant decDouble(RSyntaxElement elem) { + assert elem instanceof RSyntaxConstant; + assert ((RSyntaxConstant) elem).getValue() instanceof Number; + Number n = (Number) ((RSyntaxConstant) elem).getValue(); + return ConstantNode.create(n.doubleValue() - 1); + } + + private static RSyntaxConstant incInteger(RSyntaxElement elem) { + assert elem instanceof RSyntaxConstant; + assert ((RSyntaxConstant) elem).getValue() instanceof Number; + Number n = (Number) ((RSyntaxConstant) elem).getValue(); + return ConstantNode.create(n.intValue() + 1); + } + +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java index 915a54f6139f5840e36e127a899765f663abec06..7b78cebbe247c874e39264c65f996c488133bced 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java @@ -69,7 +69,7 @@ public abstract class C_ParseRd extends RExternalBuiltinNode.Arg9 { int con = conAsInteger.execute(conObj); int warningCalls = warningCallsAsLogical.execute(warningCallsObj); if (RRuntime.isNA(warningCalls)) { - throw RError.error(this, RError.Message.INVALID_VALUE, "warningCalls"); + throw error(RError.Message.INVALID_VALUE, "warningCalls"); } int fragment = fragmentAsLogical.execute(fragmentObj); int warndups = warnDupsAsLogical.execute(warndupsObj); @@ -86,7 +86,7 @@ public abstract class C_ParseRd extends RExternalBuiltinNode.Arg9 { RDataFactory.createLogicalVectorFromScalar((byte) warndups)); // @formatter:on } catch (Throwable ex) { - throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); + throw error(RError.Message.GENERIC, ex.getMessage()); } } @@ -94,6 +94,6 @@ public abstract class C_ParseRd extends RExternalBuiltinNode.Arg9 { @Fallback public Object parseRd(Object con, Object srcfile, Object encoding, Object verbose, Object basename, Object fragment, Object warningCalls, Object macros, Object warndupsL) { - throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); + throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java index 9685b25687c58acaaac849aabf0e6e646fc11538..98db4f99c4790b0d617a24f7ef62f6fe0aa13a9a 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java @@ -44,7 +44,7 @@ public abstract class DirChmod extends RExternalBuiltinNode.Arg2 { static { Casts casts = new Casts(DirChmod.class); casts.arg(0, "dir").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst(); - casts.arg(1).asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean()); + casts.arg(1).asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); } @Specialization @@ -77,6 +77,6 @@ public abstract class DirChmod extends RExternalBuiltinNode.Arg2 { @SuppressWarnings("unused") @Fallback protected Object fallback(Object dir, Object gws) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "dir"); + throw error(RError.Message.INVALID_ARGUMENT, "dir"); } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/Rmd5.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/Rmd5.java index 7b9d09c4a88998f7960e151953c037d2432275b1..3678eb45a28fe2fea3c93574b4ad3a8f6335bd3a 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/Rmd5.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/Rmd5.java @@ -46,7 +46,7 @@ public abstract class Rmd5 extends RExternalBuiltinNode.Arg1 { static { Casts casts = new Casts(Rmd5.class); - casts.arg(0).defaultError(RError.NO_CALLER, RError.Message.ARG_MUST_BE_CHARACTER, "files").mustBe(stringValue()); + casts.arg(0).defaultError(RError.Message.ARG_MUST_BE_CHARACTER, "files").mustBe(stringValue()); } @Specialization diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java index 576ff1bd5571c60a5808cddb9a6da9a002ebe27e..79f1b7df8b219ecad3655eb41d3a14ed379ce9a9 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java @@ -38,8 +38,8 @@ public class ToolsText { static { Casts casts = new Casts(DoTabExpand.class); - casts.arg(0, "strings").defaultError(RError.NO_CALLER, RError.Message.MACRO_CAN_BE_APPLIED_TO, "STRING_ELT()", "character vector", typeName()).mustBe(stringValue()); - casts.arg(1, "starts").defaultError(RError.NO_CALLER, RError.Message.MACRO_CAN_BE_APPLIED_TO, "INTEGER()", "integer", typeName()).mustBe(integerValue()).asIntegerVector(); + casts.arg(0, "strings").defaultError(RError.Message.MACRO_CAN_BE_APPLIED_TO, "STRING_ELT()", "character vector", typeName()).mustBe(stringValue()); + casts.arg(1, "starts").defaultError(RError.Message.MACRO_CAN_BE_APPLIED_TO, "INTEGER()", "integer", typeName()).mustBe(integerValue()).asIntegerVector(); } @Specialization @@ -110,7 +110,7 @@ public class ToolsText { } data[i] = RRuntime.LOGICAL_TRUE; } catch (IOException ex) { - RError.warning(this, RError.Message.GENERIC, "IO error during file append"); + warning(RError.Message.GENERIC, "IO error during file append"); // shouldn't happen, just continue with false result } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java index cb470182d58a282b25717ef630d53db7111478a2..bf6252a67e445eef2011f3e1ef1e760625f3a1cd 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java @@ -15,19 +15,20 @@ import java.io.IOException; import java.io.InputStream; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.conn.RConnection; import com.oracle.truffle.r.runtime.conn.StdConnections; -import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RNull; // Transcribed from GnuR, library/utils/src/io.c // Checkstyle: stop -public final class CountFields extends RExternalBuiltinNode { +public abstract class CountFields extends RExternalBuiltinNode.Arg6 { private static final int R_EOF = -1; private static final int SCAN_BLOCKSIZE = 1000; @@ -54,10 +55,56 @@ public final class CountFields extends RExternalBuiltinNode { } static { - Casts.noCasts(CountFields.class); + Casts casts = new Casts(CountFields.class); + casts.arg(0, "conn").asIntegerVector().findFirst(); + casts.arg(1, "sep").allowNull().mustBe(Predef.stringValue()).asStringVector().findFirst(); + casts.arg(2, "quote").allowNull().mustBe(Predef.stringValue()).asStringVector().findFirst(); + casts.arg(3, "nskip").asIntegerVector().findFirst(); + casts.arg(4, "blskip").asLogicalVector().findFirst().replaceNA(RRuntime.LOGICAL_TRUE).map(Predef.toBoolean()); + casts.arg(5, "commend.char").mustBe(Predef.stringValue()).asStringVector().findFirst().mustBe(Predef.length(1)); } + @Specialization @TruffleBoundary + protected Object count(int conn, Object sep, Object quote, int nskipArg, boolean blskip, String commentCharArg) { + char comChar; + if (!(commentCharArg != null && commentCharArg.length() == 1)) { + throw error(RError.Message.INVALID_ARGUMENT, "comment.char"); + } else { + comChar = commentCharArg.charAt(0); + } + + int nskip; + if (nskipArg < 0 || nskipArg == RRuntime.INT_NA) { + nskip = 0; + } else { + nskip = nskipArg; + } + + char sepChar; + if (sep instanceof RNull) { + sepChar = 0; + } else { + String s = (String) sep; + if (s == null) { + throw error(RError.Message.INVALID_ARGUMENT, "sep"); + } else { + sepChar = s.length() == 0 ? 0 : s.charAt(0); + } + } + String quoteSet; + if (quote instanceof RNull) { + quoteSet = ""; + } else { + quoteSet = (String) quote; + } + try (RConnection openConn = RConnection.fromIndex(conn).forceOpen("r")) { + return countFields(openConn, sepChar, quoteSet, nskip, blskip, comChar); + } catch (IllegalStateException | IOException ex) { + throw error(RError.Message.GENERIC, ex.getMessage()); + } + } + private static Object countFields(RConnection file, char sepChar, String quoteSet, @SuppressWarnings("unused") int nskip, boolean blskip, char comChar) throws IOException { LocalData data = new LocalData(); data.sepchar = sepChar; @@ -291,63 +338,4 @@ public final class CountFields extends RExternalBuiltinNode { // TODO locale return false; } - - // Transcribed from GnuR, library/utils/src/io.c - @Override - @TruffleBoundary - public Object call(RArgsValuesAndNames args) { - Object[] argValues = args.getArguments(); - int conn = castInt(castVector(argValues[0])); - Object sepArg = argValues[1]; - char sepChar; - Object quoteArg = argValues[2]; - int nskip = castInt(castVector(argValues[3])); - byte blskip = castLogical(castVector(argValues[4])); - String commentCharArg = isString(argValues[5]); - char comChar; - if (!(commentCharArg != null && commentCharArg.length() == 1)) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "comment.char"); - } else { - comChar = commentCharArg.charAt(0); - } - - if (nskip < 0 || nskip == RRuntime.INT_NA) { - nskip = 0; - } - if (blskip == RRuntime.LOGICAL_NA) { - blskip = RRuntime.LOGICAL_TRUE; - } - - if (sepArg instanceof RNull) { - sepChar = 0; - } else { - String s = isString(sepArg); - if (s == null) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "sep"); - } else { - if (s.length() == 0) { - sepChar = 0; - } else { - sepChar = s.charAt(0); - } - } - } - String quoteSet; - if (quoteArg instanceof RNull) { - quoteSet = ""; - } else { - String s = isString(quoteArg); - if (s == null) { - throw RError.error(this, RError.Message.GENERIC, "invalid quote symbol set"); - } else { - quoteSet = s; - } - } - try (RConnection openConn = RConnection.fromIndex(conn).forceOpen("r")) { - return countFields(openConn, sepChar, quoteSet, nskip, RRuntime.fromLogical(blskip), comChar); - } catch (IllegalStateException | IOException ex) { - errorProfile.enter(); - throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); - } - } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Crc64.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Crc64.java index 51eb47a457af6a813af1e9f27691829cd8aad73f..301ce24664ed88bad44dbc578435ac599edf9b9a 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Crc64.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Crc64.java @@ -34,8 +34,7 @@ public abstract class Crc64 extends RExternalBuiltinNode.Arg1 { static { Casts casts = new Casts(Crc64.class); - casts.arg(0).mustNotBeNull(RError.NO_CALLER, - RError.Message.INPUT_MUST_BE_STRING).mustBe(stringValue(), RError.NO_CALLER, RError.Message.INPUT_MUST_BE_STRING); + casts.arg(0).mustNotBeNull(RError.Message.INPUT_MUST_BE_STRING).mustBe(stringValue(), RError.Message.INPUT_MUST_BE_STRING); } @Specialization diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java index 00172482920056c2d34e3ed7af95a425f2b768af..d9b2e1d55b82316b3aba40c73cb621e877bef004 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java @@ -1,24 +1,13 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * 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 * - * 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. + * Copyright (c) 1995, 1996 Robert Gentleman and Ross Ihaka + * Copyright (c) 1997-2013, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates * - * 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. + * All rights reserved. */ package com.oracle.truffle.r.library.utils; @@ -30,7 +19,9 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; import java.io.IOException; import java.io.InputStream; +import java.net.HttpURLConnection; import java.net.URL; +import java.net.URLConnection; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; @@ -40,6 +31,7 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.conn.StdConnections; /** * Support for the "internal"method of "utils::download.file". TODO take note of "quiet", "mode" and @@ -59,15 +51,54 @@ public abstract class Download extends RExternalBuiltinNode.Arg5 { @Specialization @TruffleBoundary - protected int download(String urlString, String destFile, @SuppressWarnings("unused") boolean quiet, @SuppressWarnings("unused") String mode, @SuppressWarnings("unused") boolean cacheOK) { + protected int download(String urlString, String destFile, boolean quiet, @SuppressWarnings("unused") String mode, @SuppressWarnings("unused") boolean cacheOK) { try { - try (InputStream in = new URL(urlString).openStream()) { - Files.copy(in, Paths.get(destFile), StandardCopyOption.REPLACE_EXISTING); + URLConnection con = new URL(urlString).openConnection(); + try (InputStream in = con.getInputStream()) { + long len = Files.copy(in, Paths.get(destFile), StandardCopyOption.REPLACE_EXISTING); + if (!quiet) { + + String contentType = null; + if (con instanceof HttpURLConnection) { + HttpURLConnection httpCon = (HttpURLConnection) con; + contentType = httpCon.getContentType(); + } + + // Transcribed from GnuR, src/modules/internet/internet.c + + StdConnections.getStderr().writeString(String.format("Content type '%s'", contentType != null ? contentType : "unknown"), false); + if (len > 1024 * 1024) { + StdConnections.getStderr().writeString(String.format(" length %d bytes (%.1f MB)", len, len / 1024.0 / 1024.0), true); + } else if (len > 10240) { + StdConnections.getStderr().writeString(String.format(" length %d bytes (%d KB)", len, len / 1024), true); + } else if (len >= 0) { + StdConnections.getStderr().writeString(String.format(" length %d bytes", len), true); + } else { + StdConnections.getStderr().writeString(" length unknown", true); + } + StdConnections.getStderr().flush(); + } + + return 0; + } catch (IOException e) { + if (!quiet) { + + // Transcribed from GnuR, src/modules/internet/internet.c + + int responseCode = -1; + String responseMsg = null; + if (con instanceof HttpURLConnection) { + HttpURLConnection httpCon = (HttpURLConnection) con; + responseCode = httpCon.getResponseCode(); + responseMsg = httpCon.getResponseMessage(); + } + + warning(RError.Message.GENERIC, String.format("cannot open URL '%s': HTTP status was '%d %s'", urlString, responseCode, responseMsg != null ? responseMsg : "")); + } + throw e; } - return 0; } catch (IOException e) { - errorProfile.enter(); - throw RError.error(this, RError.Message.GENERIC, e.getMessage()); + throw error(RError.Message.GENERIC, e.getMessage()); } } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java index 05fca52ffdc56ddf24dba599db1f3502def339bc..86b2f791bb7d4dbf9a075bce6171d28f924a47a9 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java @@ -60,6 +60,6 @@ public abstract class Menu extends RExternalBuiltinNode.Arg1 { @Fallback @TruffleBoundary protected int menu(@SuppressWarnings("unused") Object choices) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "choices"); + throw error(RError.Message.INVALID_ARGUMENT, "choices"); } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/ObjectSize.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/ObjectSize.java index 8c17ea3fb61df57b4757e4bd49e01f024da0e3e3..6e32b3837a8ebac7312f0080635eb0c6fd0507f1 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/ObjectSize.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/ObjectSize.java @@ -22,6 +22,8 @@ */ package com.oracle.truffle.r.library.utils; +import static com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts.noCasts; + import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; @@ -37,14 +39,14 @@ import com.oracle.truffle.r.runtime.data.RTypedValue; */ public abstract class ObjectSize extends RExternalBuiltinNode.Arg1 { + static { + noCasts(ObjectSize.class); + } + private static class MyIgnoreObjectHandler implements RObjectSize.IgnoreObjectHandler { @Override public boolean ignore(Object rootObject, Object obj) { - if (obj == RNull.instance) { - return true; - } else { - return false; - } + return obj == RNull.instance; } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java index e91e16f85ac3d9346efccf14ad73c3d4497806aa..8ef4e9fb592f66cc0f89ae4b40c45ee331b81000 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java @@ -22,6 +22,11 @@ */ package com.oracle.truffle.r.library.utils; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; + import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; @@ -60,8 +65,6 @@ import com.oracle.truffle.r.runtime.instrument.InstrumentationState; import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; - /** * Implements the {@code Rprof} external. * @@ -83,11 +86,11 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFa static { Casts casts = new Casts(Rprof.class); casts.arg(0, "filename").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst(); - casts.arg(1, "append_mode").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean()); + casts.arg(1, "append_mode").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); casts.arg(2, "dinterval").asDoubleVector().findFirst(RRuntime.DOUBLE_NA); - casts.arg(3, "mem_profiling").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean()); - casts.arg(4, "gc_profiling").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean()); - casts.arg(5, "line_profiling").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean()); + casts.arg(3, "mem_profiling").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); + casts.arg(4, "gc_profiling").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); + casts.arg(5, "line_profiling").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); casts.arg(6, "numfiles").asIntegerVector().findFirst().mustBe(gte(0)); casts.arg(7, "bufsize").asIntegerVector().findFirst().mustBe(gte(0)); } @@ -108,7 +111,7 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFa try { PrintStream out = new PrintStream(new FileOutputStream(filename, append)); if (gcProfiling) { - RError.warning(this, RError.Message.GENERIC, "Rprof: gc profiling not supported"); + warning(RError.Message.GENERIC, "Rprof: gc profiling not supported"); } if (memProfiling) { RDataFactory.addListener(this); @@ -124,7 +127,7 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFa profState.initialize(out, profileThread, statementListener, intervalInMillis, lineProfiling, memProfiling); profileThread.start(); } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, String.format("Rprof: cannot open profile file '%s'", filename)); + throw error(RError.Message.GENERIC, String.format("Rprof: cannot open profile file '%s'", filename)); } } return RNull.instance; @@ -162,8 +165,7 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFa private static String getPath(RSyntaxElement node) { Source source = node.getSourceSection().getSource(); - String path = RSource.getPath(source); - return path; + return RSource.getPath(source); } private static final class ProfileThread extends Thread { diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprofmem.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprofmem.java index 9500f6f83e4113de60775b842c033a22b0eecc85..34a5b00b398ed1f03bc1408f29547dbac905126e 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprofmem.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprofmem.java @@ -78,7 +78,7 @@ public abstract class Rprofmem extends RExternalBuiltinNode.Arg3 implements RDat RDataFactory.addListener(this); RDataFactory.setTracingState(true); } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filename)); + throw error(RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filename)); } } return RNull.instance; diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java index 27d158bbc8bae512d152b6ea83ef2e9a44258e5f..00ef74c006c7d5e32b83af503cbd31168310c637 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java @@ -22,11 +22,6 @@ */ package com.oracle.truffle.r.library.utils; -import java.util.Arrays; -import java.util.TreeSet; - -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asLogicalVector; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant; @@ -35,18 +30,25 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.map; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; -import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import static com.oracle.truffle.r.runtime.RError.Message.FIRST_ARGUMENT_MUST_BE_CHARACTER; import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ARG; -import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; -import com.oracle.truffle.r.runtime.RRuntime; import static com.oracle.truffle.r.runtime.RRuntime.LOGICAL_FALSE; + +import java.util.Arrays; +import java.util.TreeSet; + +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode; +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RLogicalVector; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; public abstract class TypeConvert extends RExternalBuiltinNode.Arg5 { @@ -54,13 +56,18 @@ public abstract class TypeConvert extends RExternalBuiltinNode.Arg5 { static { Casts casts = new Casts(TypeConvert.class); - casts.arg(0).mustBe(stringValue(), SHOW_CALLER, FIRST_ARGUMENT_MUST_BE_CHARACTER).asStringVector(); - casts.arg(1).mustBe(stringValue(), SHOW_CALLER, INVALID_ARG, "'na.strings'").asStringVector(); + casts.arg(0).mustBe(stringValue(), FIRST_ARGUMENT_MUST_BE_CHARACTER).asStringVector(); + casts.arg(1).mustBe(stringValue(), INVALID_ARG, "'na.strings'").asStringVector(); casts.arg(2).mapIf(logicalValue(), chain(asLogicalVector()).with(findFirst().logicalElement(LOGICAL_FALSE)).with(toBoolean()).end(), chain(map(constant(LOGICAL_FALSE))).with(toBoolean()).end()); } + @Override + protected RBaseNode getErrorContext() { + return RError.SHOW_CALLER; + } + private static boolean isNA(String s, RAbstractStringVector naStrings) { // naStrings are in addition to NA_character_ if (RRuntime.isNA(s)) { diff --git a/com.oracle.truffle.r.native/Makefile b/com.oracle.truffle.r.native/Makefile index 37ea9afada6df6eab8e1cd5c66f064969d37200a..69ba9ce1860aaf7d021ada51424d36dc30cad552 100644 --- a/com.oracle.truffle.r.native/Makefile +++ b/com.oracle.truffle.r.native/Makefile @@ -30,6 +30,14 @@ export FASTR_NATIVE_DIR = $(TOPDIR) export R_VERSION = $(subst R-,,$(notdir $(basename $(basename $(wildcard $(FASTR_R_HOME)/libdownloads/R-*.gz))))) export GNUR_HOME = $(TOPDIR)/gnur/R-$(R_VERSION) +ifndef FASTR_RFFI +ifeq ($(FASTR_MANAGED),true) +export FASTR_RFFI = managed +else +export FASTR_RFFI = jni +endif +endif + # Completely accurate dependency analysis is very difficult for this project, so use a version number # to force a clean build, and elsewhere use sentinels to avoid rebuilding when we can't compute the # dependencies accurately. diff --git a/com.oracle.truffle.r.native/fficall/Makefile b/com.oracle.truffle.r.native/fficall/Makefile index 78b1f4b0c3f55fb10f8180ab0b4492966b9645f5..68f128ec2b78f4fc076992505b5961a2562c2ce9 100644 --- a/com.oracle.truffle.r.native/fficall/Makefile +++ b/com.oracle.truffle.r.native/fficall/Makefile @@ -39,9 +39,8 @@ R_LIBNAME := libR$(DYLIB_EXT) R_LIB := $(FASTR_LIB_DIR)/$(R_LIBNAME) JNIBOOT_LIBNAME := libjniboot$(DYLIB_EXT) JNIBOOT_LIB := $(FASTR_LIB_DIR)/$(JNIBOOT_LIBNAME) - -FASTR_COMPILERS_DIR := $(FASTR_R_HOME)/mx.fastr/compilers -HAVE_SULONG := $(shell $(FASTR_COMPILERS_DIR)/have_sulong) +CACCESS_LIBNAME := libcaccess$(DYLIB_EXT) +CACCESS_LIB := $(FASTR_LIB_DIR)/$(CACCESS_LIBNAME) ifeq ($(OS_NAME), Darwin) VERSION_FLAGS := -current_version $(R_VERSION) -compatibility_version $(R_VERSION) @@ -50,13 +49,16 @@ endif BLAS_TARGET := $(FASTR_LIB_DIR)/libRblas$(DYLIB_EXT) LAPACK_TARGET := $(FASTR_LIB_DIR)/libRlapack$(DYLIB_EXT) -all: $(R_LIB) $(JNIBOOT_LIB) +all: $(R_LIB) # use sentinels to avoid (usually unnecessary) rebuilds. # N.B. if things change in the subdirs, a clean must be invoked # to remove the sentinels -$(R_LIB): jni.done +$(R_LIB): fficall.done +ifeq ($(FASTR_RFFI),managed) + # nop +else ifeq ($(OS_NAME),Darwin) $(DYLIB_LD) $(DYLIB_LDFLAGS) -Wl,-rpath,@loader_path/ -o $(R_LIB) $(wildcard lib/*.o) -L$(FASTR_LIB_DIR) -lRblas -lRlapack -lpcre -lz $(VERSION_FLAGS) install_name_tool -change libRblas.dylib @rpath/libRblas.dylib $(R_LIB) @@ -67,32 +69,65 @@ ifeq ($(OS_NAME),Darwin) else $(DYLIB_LD) $(DYLIB_LDFLAGS) $(shell echo $(PKG_LDFLAGS_OVERRIDE)) -Wl,-rpath,'$$ORIGIN' -o $(R_LIB) $(wildcard lib/*.o) -L$(FASTR_LIB_DIR) -lRblas -lRlapack -lpcre -lz endif +endif # managed -jni.done: - $(MAKE) -C src/common all - $(MAKE) -C src/jni all -ifeq ($(HAVE_SULONG),yes) +ifeq ($(FASTR_RFFI),managed) +fficall.done: common.done + touch fficall.done +else +ifeq ($(FASTR_RFFI),nfi) +fficall.done: common.done + $(MAKE) -C src/truffle_nfi all + touch fficall.done +else +ifeq ($(FASTR_RFFI),llvm) +fficall.done: common.done $(MAKE) -C src/truffle_llvm all -endif - touch jni.done + touch fficall.done +else +ifeq ($(FASTR_RFFI),jni) +fficall.done: common.done $(JNIBOOT_LIB) + $(MAKE) -C src/jni all + +jniboot.done: + $(MAKE) -C src/jniboot all + touch jniboot.done $(JNIBOOT_LIB): jniboot.done $(DYLIB_LD) $(DYLIB_LDFLAGS) -o $(JNIBOOT_LIB) src/jniboot/jniboot.o $(VERSION_FLAGS) ifeq ($(OS_NAME),Darwin) install_name_tool -id @rpath/libjniboot.dylib $(JNIBOOT_LIB) endif +else + $(error unknown value for FASTR_RFFI) +endif + touch fficall.done +endif +endif +endif -jniboot.done: - $(MAKE) -C src/jniboot all - touch jniboot.done +common.done: + $(MAKE) -C src/common all + +$(CACCESS_LIB): src/caccess/caccess.o + $(DYLIB_LD) $(DYLIB_LDFLAGS) -o $(CACCESS_LIB) src/caccess/caccess.o $(VERSION_FLAGS) +ifeq ($(OS_NAME),Darwin) + install_name_tool -id @rpath/libcaccess.dylib $(CACCESS_LIB) +endif clean: $(MAKE) -C src/common clean - $(MAKE) -C src/jni clean -ifeq ($(HAVE_SULONG),yes) +ifeq ($(FASTR_RFFI),nfi) + $(MAKE) -C src/truffle_nfi clean +else +ifeq ($(FASTR_RFFI),llvm) $(MAKE) -C src/truffle_llvm clean +else + $(MAKE) -C src/jni clean +endif endif rm -rf $(R_LIB) rm -rf $(JNIBOOT_LIB) - rm -rf jni.done jniboot.done + rm -rf $(CACCESS_LIB) + rm -rf fficall.done diff --git a/com.oracle.truffle.r.native/fficall/src/caccess/Makefile b/com.oracle.truffle.r.native/fficall/src/caccess/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..de9823908ec737bd08446e1b290fbd40230ca647 --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/caccess/Makefile @@ -0,0 +1,34 @@ +# +# 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. +# + +ifneq ($(MAKECMDGOALS),clean) +include $(TOPDIR)/platform.mk +endif + + +.PHONY: all + +all: caccess.o + +caccess.o: caccess.c + $(CC) $(CFLAGS) -c caccess.c -o $@ diff --git a/com.oracle.truffle.r.native/fficall/src/caccess/caccess.c b/com.oracle.truffle.r.native/fficall/src/caccess/caccess.c new file mode 100644 index 0000000000000000000000000000000000000000..6743e91b48a8436d2f36d0ae9f41da0926747e0a --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/caccess/caccess.c @@ -0,0 +1,38 @@ +/* + * 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. + */ + +int caccess_read_pointer_int(int *address) { + return *address; +} + +double caccess_read_pointer_double(double *address) { + return *address; +} + +int caccess_read_array_int(int *address, int index) { + return address[index]; +} + +double caccess_read_array_double(double *address, int index) { + return address[index]; +} diff --git a/com.oracle.truffle.r.native/fficall/src/common/Rinternals_common.c b/com.oracle.truffle.r.native/fficall/src/common/Rinternals_common.c new file mode 100644 index 0000000000000000000000000000000000000000..b4c88dff801bb60a539fdf0415e6e698ed2209e4 --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/common/Rinternals_common.c @@ -0,0 +1,191 @@ +/* + * 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. + */ +#include <Rinternals.h> + +// This file includes all implementations that arise from Rinternals.h that +// are independent, or largely independent, of the RFFI implementation. + +Rboolean Rf_isReal(SEXP x) { + return TYPEOF(x) == REALSXP; +} + +Rboolean Rf_isSymbol(SEXP x) { + return TYPEOF(x) == SYMSXP; +} + +Rboolean Rf_isComplex(SEXP x) { + return TYPEOF(x) == CPLXSXP; +} + +Rboolean Rf_isEnvironment(SEXP x) { + return TYPEOF(x) == ENVSXP; +} + +Rboolean Rf_isExpression(SEXP x) { + return TYPEOF(x) == EXPRSXP; +} + +Rboolean Rf_isLogical(SEXP x) { + return TYPEOF(x) == LGLSXP; +} + +SEXP GetOption(SEXP tag, SEXP rho) +{ + return GetOption1(tag); // RFFI impl dependent +} + +int GetOptionCutoff(void) +{ + int w; + w = asInteger(GetOption1(install("deparse.cutoff"))); + if (w == NA_INTEGER || w <= 0) { + warning("invalid 'deparse.cutoff', used 60"); + w = 60; + } + return w; +} + +#define R_MIN_WIDTH_OPT 10 +#define R_MAX_WIDTH_OPT 10000 +#define R_MIN_DIGITS_OPT 0 +#define R_MAX_DIGITS_OPT 22 + +int GetOptionWidth(void) +{ + int w; + w = asInteger(GetOption1(install("width"))); + if (w < R_MIN_WIDTH_OPT || w > R_MAX_WIDTH_OPT) { + warning("invalid printing width, used 80"); + return 80; + } + return w; +} + +int GetOptionDigits(void) +{ + int d; + d = asInteger(GetOption1(install("digits"))); + if (d < R_MIN_DIGITS_OPT || d > R_MAX_DIGITS_OPT) { + warning("invalid printing digits, used 7"); + return 7; + } + return d; +} + +Rboolean Rf_GetOptionDeviceAsk(void) +{ + int ask; + ask = asLogical(GetOption1(install("device.ask.default"))); + if(ask == NA_LOGICAL) { + warning("invalid value for \"device.ask.default\", using FALSE"); + return FALSE; + } + return ask != 0; +} + +void *DATAPTR(SEXP x) { + int type = TYPEOF(x); + if (type == INTSXP) { + return INTEGER(x); + } else if (type == REALSXP) { + return REAL(x); + } else if (type == LGLSXP) { + return LOGICAL(x); + } else { + printf("DATAPTR %d\n", type); + unimplemented("R_DATAPTR"); + return NULL; + } +} + +int R_check_class_and_super(SEXP x, const char **valid, SEXP rho) { + int ans; + SEXP cl = PROTECT(asChar(getAttrib(x, R_ClassSymbol))); + const char *class = CHAR(cl); + for (ans = 0; ; ans++) { + if (!strlen(valid[ans])) // empty string + break; + if (!strcmp(class, valid[ans])) { + UNPROTECT(1); /* cl */ + return ans; + } + } + /* if not found directly, now search the non-virtual super classes :*/ + if(IS_S4_OBJECT(x)) { + /* now try the superclasses, i.e., try is(x, "...."); superCl := + .selectSuperClasses(getClass("....")@contains, dropVirtual=TRUE) */ + SEXP classExts, superCl, _call; + // install() results cached anyway so the following variables could be non-static if needed + static SEXP s_contains = NULL, s_selectSuperCl = NULL; + int i; + if(!s_contains) { + s_contains = install("contains"); + s_selectSuperCl = install(".selectSuperClasses"); + } + SEXP classDef = PROTECT(R_getClassDef(class)); + PROTECT(classExts = R_do_slot(classDef, s_contains)); + PROTECT(_call = lang3(s_selectSuperCl, classExts, + /* dropVirtual = */ ScalarLogical(1))); + superCl = eval(_call, rho); + UNPROTECT(3); /* _call, classExts, classDef */ + PROTECT(superCl); + for(i=0; i < LENGTH(superCl); i++) { + const char *s_class = CHAR(STRING_ELT(superCl, i)); + for (ans = 0; ; ans++) { + if (!strlen(valid[ans])) + break; + if (!strcmp(s_class, valid[ans])) { + UNPROTECT(2); /* superCl, cl */ + return ans; + } + } + } + UNPROTECT(1); /* superCl */ + } + UNPROTECT(1); /* cl */ + return -1; +} + +int R_check_class_etc_helper (SEXP x, const char **valid, SEXP (*getMethodsNamespace)()) { + // install() results cached anyway so the following variables could be non-static if needed + static SEXP meth_classEnv = NULL; + SEXP cl = getAttrib(x, R_ClassSymbol), rho = R_GlobalEnv, pkg; + if (!meth_classEnv) + meth_classEnv = install(".classEnv"); + + pkg = getAttrib(cl, R_PackageSymbol); /* ==R== packageSlot(class(x)) */ + if (!isNull(pkg)) { /* find rho := correct class Environment */ + SEXP clEnvCall; + // FIXME: fails if 'methods' is not loaded. + PROTECT(clEnvCall = lang2(meth_classEnv, cl)); + SEXP methodsNamespace = getMethodsNamespace(); + rho = eval(clEnvCall, methodsNamespace); + UNPROTECT(1); + if (!isEnvironment(rho)) + error(_("could not find correct environment; please report!")); + } + PROTECT(rho); + int res = R_check_class_and_super(x, valid, rho); + UNPROTECT(1); + return res; +} diff --git a/com.oracle.truffle.r.native/fficall/src/common/Rinternals_common.h b/com.oracle.truffle.r.native/fficall/src/common/Rinternals_common.h new file mode 100644 index 0000000000000000000000000000000000000000..6d78b52544b54770ae4e65f4d5bbfb7ae78a6e0f --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/common/Rinternals_common.h @@ -0,0 +1,26 @@ +/* + * 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 + * 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. + */ +#include <Rinternals.h> + +// Factors out the RFFI mechanism for getting the methods namespace. +int R_check_class_etc_helper (SEXP x, const char **valid, SEXP (*getMethodsNamespace)()); diff --git a/com.oracle.truffle.r.native/fficall/src/common/inlined_fastr.c b/com.oracle.truffle.r.native/fficall/src/common/inlined_fastr.c index 72b60fd49b8e62b81b4ca4eff6362383c4d798ed..184f0869edeb7e2a760cdf6364a5f9242211d572 100644 --- a/com.oracle.truffle.r.native/fficall/src/common/inlined_fastr.c +++ b/com.oracle.truffle.r.native/fficall/src/common/inlined_fastr.c @@ -6,7 +6,7 @@ * Copyright (c) 1995, 1996, 1997 Robert Gentleman and Ross Ihaka * Copyright (c) 1995-2014, The R Core Team * Copyright (c) 2002-2008, The R Foundation - * Copyright (c) 2015, 2016, Oracle and/or its affiliates + * Copyright (c) 2015, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -545,3 +545,4 @@ Rboolean IS_BYTES(SEXP x) { return FALSE; } Rboolean IS_LATIN1(SEXP x) { return FALSE; } Rboolean IS_ASCII(SEXP x) { return FALSE; } Rboolean IS_UTF8(SEXP x) { return TRUE; } +Rboolean ENC_KNOWN(SEXP x) { return TRUE; } diff --git a/com.oracle.truffle.r.native/fficall/src/common/unimplemented.c b/com.oracle.truffle.r.native/fficall/src/common/unimplemented.c index 28dc2ccca5f9db279856d872988510eb0300b403..4dbe601ee0e0828bf610d94431bff830a46a6e3e 100644 --- a/com.oracle.truffle.r.native/fficall/src/common/unimplemented.c +++ b/com.oracle.truffle.r.native/fficall/src/common/unimplemented.c @@ -5,7 +5,7 @@ * * Copyright (c) 1995-2015, The R Core Team * Copyright (c) 2003, The R Foundation - * Copyright (c) 2015, 2016, Oracle and/or its affiliates + * Copyright (c) 2015, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -142,6 +142,7 @@ void* PRIMFUN(SEXP x) { SEXP coerceToSymbol(SEXP v) { unimplemented("coerceToSymbol"); + return NULL; } int IntegerFromString(SEXP a, int* b) { diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Connections.c b/com.oracle.truffle.r.native/fficall/src/jni/Connections.c index 812f804dcd84b3b3e8320344422f94f1e6bbadd3..5a7fbf2b020fc89449638892db907504afa229fc 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/Connections.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/Connections.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, 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 @@ -21,18 +21,409 @@ * questions. */ +#include <assert.h> #include <rffiutils.h> #include <R_ext/Connections.h> + +static jmethodID readConnMethodID; +static jmethodID writeConnMethodID; +static jmethodID getConnMethodID; +static jmethodID getConnClassMethodID; +static jmethodID getSummaryDescMethodID; +static jmethodID isSeekableMethodID; +static jmethodID getOpenModeMethodID; +static jmethodID newCustomConnectionMethodID; + +static jbyteArray wrap(JNIEnv *thisenv, void* buf, size_t n) { + jbyteArray barr = (*thisenv)->NewByteArray(thisenv, n); + (*thisenv)->SetByteArrayRegion(thisenv, barr, 0, n, buf); + return barr; +} + +/* + * Returns the file descriptor of the connection if possible. + * Otherwise an error is issued. + */ +static int getFd(Rconnection con) { + return (int) con->id; +} + +/* + * Sets the file descriptor for the connection. + */ +static void setFd(Rconnection con, jint fd) { + con->id = (void *) (jlong) fd; +} + + +void init_connections(JNIEnv *env) { + /* int readConn(int, byte[]) */ + readConnMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ReadConnection", "(I[B)I", 0); + + /* int writeConn(int, byte[]) */ + writeConnMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_WriteConnection", "(I[B)I", 0); + + /* RConnection getConnection(int) */ + getConnMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_GetConnection", "(I)Ljava/lang/Object;", 0); + + + /* String getConnectionClassString(BaseRConnection) */ + getConnClassMethodID = checkGetMethodID(env, UpCallsRFFIClass, "getConnectionClassString", "(Ljava/lang/Object;)Ljava/lang/String;", 0); + + /* String getSummaryDescription(BaseRConnection) */ + getSummaryDescMethodID = checkGetMethodID(env, UpCallsRFFIClass, "getSummaryDescription", "(Ljava/lang/Object;)Ljava/lang/String;", 0); + + /* boolean isSeekable(BaseRConnection) */ + isSeekableMethodID = checkGetMethodID(env, UpCallsRFFIClass, "isSeekable", "(Ljava/lang/Object;)Z", 0); + + /* String getOpenModeString(BaseRConnection) */ + getOpenModeMethodID = checkGetMethodID(env, UpCallsRFFIClass, "getOpenModeString", "(Ljava/lang/Object;)Ljava/lang/String;", 0); + + /* int R_new_custom_connection(String, String, String) */ + newCustomConnectionMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_new_custom_connection", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0); +} + +static char *connStringToChars(JNIEnv *env, jstring string) { + jsize len = (*env)->GetStringUTFLength(env, string); + const char *stringChars = (*env)->GetStringUTFChars(env, string, NULL); + char *copyChars = malloc((len + 1)*sizeof(char)); + memcpy(copyChars, stringChars, len*sizeof(char)); + copyChars[len] = 0; + (*env)->ReleaseStringUTFChars(env, string, stringChars); + (*env)->DeleteLocalRef(env, string); + return copyChars; +} + +/* ------------------- null connection functions --------------------- */ + +static Rboolean NORET null_open(Rconnection con) +{ + error(_("%s not enabled for this connection"), "open"); +} + +static void null_close(Rconnection con) +{ + con->isopen = FALSE; +} + +static void null_destroy(Rconnection con) +{ + if(con->private) free(con->private); +} + +static int NORET null_vfprintf(Rconnection con, const char *format, va_list ap) +{ + error(_("%s not enabled for this connection"), "printing"); +} + +static int NORET null_fgetc(Rconnection con) +{ + error(_("%s not enabled for this connection"), "'getc'"); +} + +static double NORET null_seek(Rconnection con, double where, int origin, int rw) +{ + error(_("%s not enabled for this connection"), "'seek'"); +} + +static void NORET null_truncate(Rconnection con) +{ + error(_("%s not enabled for this connection"), "truncation"); +} + +static int null_fflush(Rconnection con) +{ + return 0; +} + +static size_t NORET null_read(void *ptr, size_t size, size_t nitems, + Rconnection con) +{ + error(_("%s not enabled for this connection"), "'read'"); +} + +static size_t NORET null_write(const void *ptr, size_t size, size_t nitems, + Rconnection con) +{ + error(_("%s not enabled for this connection"), "'write'"); +} + +static void init_con(Rconnection new, char *description, int enc, + const char * const mode) +{ + new->description = description; + new->enc = enc; + strncpy(new->mode, mode, 4); new->mode[4] = '\0'; + new->isopen = new->incomplete = new->blocking = new->isGzcon = FALSE; + new->canread = new->canwrite = TRUE; /* in principle */ + new->canseek = FALSE; + new->text = TRUE; + new->open = &null_open; + new->close = &null_close; + new->destroy = &null_destroy; + new->vfprintf = &null_vfprintf; + new->fgetc = new->fgetc_internal = &null_fgetc; + new->seek = &null_seek; + new->truncate = &null_truncate; + new->fflush = &null_fflush; + new->read = &null_read; + new->write = &null_write; + new->nPushBack = 0; + new->save = new->save2 = -1000; + new->private = NULL; + new->inconv = new->outconv = NULL; + new->UTF8out = FALSE; + new->id = 0; + new->ex_ptr = NULL; + new->status = NA_INTEGER; +} + SEXP R_new_custom_connection(const char *description, const char *mode, const char *class_name, Rconnection *ptr) { - return unimplemented("R_new_custom_connection"); + JNIEnv *thisenv = getEnv(); + Rconnection new; + SEXP ans, class; + + new = (Rconnection) malloc(sizeof(struct Rconn)); + if (!new) + error(_("allocation of %s connection failed"), class_name); + + jstring jsDescription = (*thisenv)->NewStringUTF(thisenv, description); + jstring jsMode = (*thisenv)->NewStringUTF(thisenv, mode); + jstring jsClassName = (*thisenv)->NewStringUTF(thisenv, class_name); + jobject addrObj = R_MakeExternalPtr(new, R_NilValue, R_NilValue); + ans = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, newCustomConnectionMethodID, jsDescription, jsMode, jsClassName, addrObj); + if (ans) { + + new->class = (char *) malloc(strlen(class_name) + 1); + if (!new->class) { + free(new); + error(_("allocation of %s connection failed"), class_name); + } + strcpy(new->class, class_name); + new->description = (char *) malloc(strlen(description) + 1); + if (!new->description) { + free(new->class); + free(new); + error(_("allocation of %s connection failed"), class_name); + } + init_con(new, (char *) description, CE_NATIVE, mode); + /* all ptrs are init'ed to null_* so no need to repeat that, + but the following two are useful tools which could not be accessed otherwise */ + // TODO dummy_vfprintf and dummy_fgetc not implemented yet +// new->vfprintf = &dummy_vfprintf; +// new->fgetc = &dummy_fgetc; + + /* new->blocking = block; */ + new->encname[0] = 0; /* "" (should have the same effect as "native.enc") */ + new->ex_ptr = R_MakeExternalPtr(new->id, install("connection"), R_NilValue); + + class = allocVector(STRSXP, 2); + SET_STRING_ELT(class, 0, mkChar(class_name)); + SET_STRING_ELT(class, 1, mkChar("connection")); + classgets(ans, class); +// setAttrib(ans, R_ConnIdSymbol, new->ex_ptr); + + if (ptr) { + ptr[0] = new; + } + } + + return ans; +} + +/* + * The address of the Rconnection struct is passed to Java. + * Since down calls can only have Object parameters, we put the address into an int vector. + * Position 0 is the lower part and position 1 is the higher part of the address. + * This currently assumes max. 64-bit addresses ! + */ +static Rconnection convertToAddress(SEXP addrObj) { + if(!inherits(addrObj, "externalptr")) { + error(_("invalid address object")); + } + return (Rconnection) R_ExternalPtrAddr(addrObj); + +} + +/* + * This function is used as Java down call function to query the value of a connection's flag. + * DO NOT CHANGE ITS SIGNATURE ! + * If changing the signature is unavoidable, adapt it in class 'NativeConnections'. + */ +SEXP __GetFlagNativeConnection(SEXP rConnAddrObj, jstring jname) { + JNIEnv *thisenv = getEnv(); + Rconnection con = convertToAddress(rConnAddrObj); + const char *name = connStringToChars(thisenv, jname); + Rboolean result = 0; + + if(strcmp(name, "text") == 0) { + result = con->text; + } else if(strcmp(name, "isopen") == 0) { + result = con->isopen; + }else if(strcmp(name, "incomplete") == 0) { + result = con->incomplete; + }else if(strcmp(name, "canread") == 0) { + result = con->canread; + }else if(strcmp(name, "canwrite") == 0) { + result = con->canwrite; + }else if(strcmp(name, "canseek") == 0) { + result = con->canseek; + }else if(strcmp(name, "blocking") == 0) { + result = con->blocking; + } + free((char *)name); + + return ScalarLogical(result); +} + +/* + * This function is used as Java down call function to invoke the open function of a natively created connection. + * DO NOT CHANGE ITS SIGNATURE ! + * If changing the signature is unavoidable, adapt it in class 'NativeConnections'. + */ +SEXP __OpenNativeConnection(SEXP rConnAddrObj) { + Rconnection con = convertToAddress(rConnAddrObj); + Rboolean success = con->open(con); + return ScalarLogical(success); +} + +/* + * This function is used as Java down call function to invoke the open function of a natively created connection. + * DO NOT CHANGE ITS SIGNATURE ! + * If changing the signature is unavoidable, adapt it in class 'NativeConnections'. + */ +SEXP __CloseNativeConnection(SEXP rConnAddrObj) { + Rconnection con = convertToAddress(rConnAddrObj); + con->close(con); + return NULL; +} + +/* + * This function is used as Java down call function to invoke the read function of a natively created connection. + * DO NOT CHANGE ITS SIGNATURE ! + * If changing the signature is unavoidable, adapt it in class 'NativeConnections'. + */ +SEXP __ReadNativeConnection(SEXP rConnAddrObj, jbyteArray bufObj, SEXP nVec) { + JNIEnv *thisenv = getEnv(); + int n = asInteger(nVec); + Rconnection con = convertToAddress(rConnAddrObj); + void *tmp_buf = (*thisenv)->GetByteArrayElements(thisenv, bufObj, NULL); + size_t nread = con->read(tmp_buf, 1, n, con); + // copy back and release buffer + (*thisenv)->ReleaseByteArrayElements(thisenv, bufObj, tmp_buf, JNI_COMMIT); + return ScalarInteger(nread); +} + +/* + * This function is used as Java down call function to invoke the write function of a natively created connection. + * DO NOT CHANGE ITS SIGNATURE ! + * If changing the signature is unavoidable, adapt it in class 'NativeConnections'. + */ +SEXP __WriteNativeConnection(SEXP rConnAddrObj, jbyteArray bufObj, SEXP nVec) { + JNIEnv *thisenv = getEnv(); + int n = asInteger(nVec); + Rconnection con = convertToAddress(rConnAddrObj); + void *bytes = (*thisenv)->GetByteArrayElements(thisenv, bufObj, NULL); + size_t nwritten = con->write(bytes, 1, n, con); + // just release buffer + (*thisenv)->ReleaseByteArrayElements(thisenv, bufObj, bytes, JNI_ABORT); + return ScalarInteger(nwritten); +} + +/* + * This function is used as Java down call function to invoke the seek function of a natively created connection. + * DO NOT CHANGE ITS SIGNATURE ! + * If changing the signature is unavoidable, adapt it in class 'NativeConnections'. + */ +SEXP __SeekNativeConnection(SEXP rConnAddrObj, SEXP whereObj, SEXP originObj, SEXP rwObj) { + Rconnection con = convertToAddress(rConnAddrObj); + double where = asReal(whereObj); + int origin = asInteger(originObj); + int rw = asInteger(rwObj); + double oldPos = con->seek(con, where, origin, rw); + return ScalarReal(oldPos); } size_t R_ReadConnection(Rconnection con, void *buf, size_t n) { - return (size_t) unimplemented("R_ReadConnection"); + JNIEnv *thisenv = getEnv(); + jbyteArray barr = (*thisenv)->NewByteArray(thisenv, n); + + jint result = (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, readConnMethodID, getFd(con), barr); + size_t readBytes = result >= 0 ? (size_t) result : 0; + assert(result <= (ssize_t) n); + if(result > 0) { + (*thisenv)->GetByteArrayRegion(thisenv, barr, 0, result, buf); + } + return readBytes; } size_t R_WriteConnection(Rconnection con, void *buf, size_t n) { - return (size_t) unimplemented("R_WriteConnection"); + JNIEnv *thisenv = getEnv(); + jbyteArray barr = wrap(thisenv, buf, n); + + jint result = (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, writeConnMethodID, getFd(con), barr); + return result >= 0 ? (size_t) result : 0; +} + +Rconnection R_GetConnection(SEXP sConn) { + if (!inherits(sConn, "connection")) { + error(_("invalid connection")); + } + + int fd = asInteger(sConn); + + JNIEnv *thisenv = getEnv(); + jobject jRconn = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, getConnMethodID, fd); + + // query getConnectionClassString + jstring jConnClass = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, getConnClassMethodID, jRconn); + const char *sConnClass; + if (jConnClass != 0) { + sConnClass = connStringToChars(thisenv, jConnClass); + } + + // query getSummaryDescription + jstring jSummaryDesc = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, getSummaryDescMethodID, jRconn); + char *sSummaryDesc; + if (jSummaryDesc != 0) { + sSummaryDesc = connStringToChars(thisenv, jSummaryDesc); + } + + // query isSeekable() + jboolean seekable = (*thisenv)->CallBooleanMethod(thisenv, UpCallsRFFIObject, isSeekableMethodID, jRconn); + + // query getOpenMode + jstring jOpenMode = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, getOpenModeMethodID, jRconn); + char *sOpenMode; + if (jOpenMode != 0) { + sOpenMode = connStringToChars(thisenv, jOpenMode); + } + + Rconnection new = (Rconnection) malloc(sizeof(struct Rconn)); + if (!new) { + error(_("allocation of file connection failed")); + } + + init_con(new, sSummaryDesc, 0, sOpenMode); + free(sOpenMode); + new->class = (char *) sConnClass; + new->canseek = seekable; + + setFd(new, fd); + +// TODO implement up-call functions and set them +// new->open = &file_open; +// new->close = &file_close; +// new->vfprintf = &file_vfprintf; +// new->fgetc_internal = &file_fgetc_internal; +// new->fgetc = &dummy_fgetc; +// new->seek = &file_seek; +// new->truncate = &file_truncate; +// new->fflush = &file_fflush; +// new->read = &file_read; +// new->write = &file_write; + + return new; } diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Makefile b/com.oracle.truffle.r.native/fficall/src/jni/Makefile index fbbb5f7439dba6a5a6e0c261645d4a25922585f1..1108df184f50021c2a65cecabccb3680cff33a2b 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/Makefile +++ b/com.oracle.truffle.r.native/fficall/src/jni/Makefile @@ -38,7 +38,7 @@ C_OBJECTS := $(patsubst %.c,$(OBJ)/%.o,$(C_SOURCES)) JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/$(JDK_OS_DIR) FFI_INCLUDES = -I$(TOPDIR)/include -I$(TOPDIR)/include/R_ext -LOCAL_INCLUDES = -I . -I $(abspath ../include) +LOCAL_INCLUDES = -I . -I $(abspath ../include) -I $(abspath ../common) INCLUDES := $(LOCAL_INCLUDES) $(JNI_INCLUDES) $(FFI_INCLUDES) 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 d6e16e35f3ab64c5b53d685795487bde09fe74b5..ebf731f63f9664d3921bba9ba643b1af4c6206d0 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 @@ -5,7 +5,7 @@ * * Copyright (c) 1995-2012, The R Core Team * Copyright (c) 2003, The R Foundation - * Copyright (c) 2014, 2016, Oracle and/or its affiliates + * Copyright (c) 2014, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -151,5 +151,5 @@ DL_FUNC R_FindSymbol(char const *name, char const *pkg, DllInfo *R_getEmbeddingDllInfo(void) { JNIEnv *thisenv = getEnv(); - return (*thisenv)->CallStaticObjectMethod(thisenv, JNI_PkgInitClass, getEmbeddingDllInfoID); + return (DllInfo*) (*thisenv)->CallStaticObjectMethod(thisenv, JNI_PkgInitClass, getEmbeddingDllInfoID); } diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c b/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c index c9b70d1372a81627aed4d2e6a8c8343ea36edf20..c38eab99ff203ac76050c0cbcb3e6c973662168d 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c @@ -20,7 +20,6 @@ extern char **environ; static JavaVM *javaVM; -static jobject engine; static int initialized = 0; static char *java_home; @@ -163,15 +162,14 @@ int Rf_initialize_R(int argc, char *argv[]) { rembeddedClass = checkFindClass(jniEnv, "com/oracle/truffle/r/engine/shell/REmbedded"); rStartParamsClass = checkFindClass(jniEnv, "com/oracle/truffle/r/runtime/RStartParams"); jclass stringClass = checkFindClass(jniEnv, "java/lang/String"); - jmethodID initializeMethod = checkGetMethodID(jniEnv, rembeddedClass, "initializeR", - "([Ljava/lang/String;)Lcom/oracle/truffle/api/vm/PolyglotEngine;", 1); + jmethodID initializeMethod = checkGetMethodID(jniEnv, rembeddedClass, "initializeR", "([Ljava/lang/String;)V", 1); jobjectArray argsArray = (*jniEnv)->NewObjectArray(jniEnv, argc, stringClass, NULL); for (int i = 0; i < argc; i++) { jstring arg = (*jniEnv)->NewStringUTF(jniEnv, argv[i]); (*jniEnv)->SetObjectArrayElement(jniEnv, argsArray, i, arg); } // Can't TRACE this upcall as system not initialized - engine = checkRef(jniEnv, (*jniEnv)->CallStaticObjectMethod(jniEnv, rembeddedClass, initializeMethod, argsArray)); + (*jniEnv)->CallStaticObjectMethod(jniEnv, rembeddedClass, initializeMethod, argsArray); initialized++; return 0; } @@ -250,15 +248,15 @@ static void setupOverrides(void); void setup_Rmainloop(void) { JNIEnv *jniEnv = getEnv(); - jmethodID setupMethod = checkGetMethodID(jniEnv, rembeddedClass, "setupRmainloop", "(Lcom/oracle/truffle/api/vm/PolyglotEngine;)V", 1); - (*jniEnv)->CallStaticVoidMethod(jniEnv, rembeddedClass, setupMethod, engine); + jmethodID setupMethod = checkGetMethodID(jniEnv, rembeddedClass, "setupRmainloop", "()V", 1); + (*jniEnv)->CallStaticVoidMethod(jniEnv, rembeddedClass, setupMethod); } void run_Rmainloop(void) { JNIEnv *jniEnv = getEnv(); setupOverrides(); - jmethodID mainloopMethod = checkGetMethodID(jniEnv, rembeddedClass, "runRmainloop", "(Lcom/oracle/truffle/api/vm/PolyglotEngine;)V", 1); - (*jniEnv)->CallStaticVoidMethod(jniEnv, rembeddedClass, mainloopMethod, engine); + jmethodID mainloopMethod = checkGetMethodID(jniEnv, rembeddedClass, "runRmainloop", "()V", 1); + (*jniEnv)->CallStaticVoidMethod(jniEnv, rembeddedClass, mainloopMethod); } void Rf_mainloop(void) { diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c index affaab5f727fbad00ec93247b196107031d0d2f7..1f63778f8fcd6e079a470f5f67b58bb504920c18 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c @@ -22,6 +22,7 @@ */ #include <rffiutils.h> #include <string.h> +#include <Rinternals_common.h> // Most everything in RInternals.h @@ -36,14 +37,14 @@ static jmethodID Rf_ScalarIntegerMethodID; static jmethodID Rf_ScalarDoubleMethodID; static jmethodID Rf_ScalarStringMethodID; static jmethodID Rf_ScalarLogicalMethodID; -static jmethodID Rf_allocateVectorMethodID; -static jmethodID Rf_allocateArrayMethodID; -static jmethodID Rf_allocateMatrixMethodID; +static jmethodID Rf_allocVectorMethodID; +static jmethodID Rf_allocArrayMethodID; +static jmethodID Rf_allocMatrixMethodID; static jmethodID Rf_duplicateMethodID; -static jmethodID Rf_anyDuplicatedMethodID; +static jmethodID Rf_any_duplicatedMethodID; static jmethodID Rf_consMethodID; static jmethodID Rf_evalMethodID; -static jmethodID Rf_findfunMethodID; +static jmethodID Rf_findFunMethodID; static jmethodID Rf_defineVarMethodID; static jmethodID Rf_findVarMethodID; static jmethodID Rf_findVarInFrameMethodID; @@ -52,6 +53,7 @@ static jmethodID Rf_getAttribMethodID; static jmethodID Rf_setAttribMethodID; static jmethodID Rf_isStringMethodID; static jmethodID Rf_isNullMethodID; +static jmethodID Rf_installCharMethodID; static jmethodID Rf_installMethodID; static jmethodID Rf_warningcallMethodID; static jmethodID Rf_warningMethodID; @@ -86,9 +88,13 @@ jmethodID RAW_MethodID; jmethodID INTEGER_MethodID; jmethodID REAL_MethodID; jmethodID LOGICAL_MethodID; +jmethodID logNotCharSXPWrapperMethodID; static jmethodID STRING_ELT_MethodID; static jmethodID VECTOR_ELT_MethodID; static jmethodID LENGTH_MethodID; +static jmethodID R_do_slot_MethodID; +static jmethodID R_do_slot_assign_MethodID; +static jmethodID R_MethodsNamespaceMethodID; static jmethodID Rf_asIntegerMethodID; static jmethodID Rf_asRealMethodID; static jmethodID Rf_asCharMethodID; @@ -103,7 +109,8 @@ static jmethodID TYPEOF_MethodID; static jmethodID OBJECT_MethodID; static jmethodID DUPLICATE_ATTRIB_MethodID; static jmethodID IS_S4_OBJECTMethodID; -static jmethodID logNotCharSXPWrapperMethodID; +static jmethodID SET_S4_OBJECTMethodID; +static jmethodID UNSET_S4_OBJECTMethodID; static jmethodID R_tryEvalMethodID; static jmethodID RDEBUGMethodID; static jmethodID SET_RDEBUGMethodID; @@ -113,6 +120,7 @@ static jmethodID ENCLOSMethodID; static jmethodID PRVALUEMethodID; static jmethodID R_lsInternal3MethodID; static jmethodID R_do_MAKE_CLASS_MethodID; +static jmethodID R_do_new_object_MethodID; static jmethodID PRSEENMethodID; static jmethodID PRENVMethodID; static jmethodID R_PromiseExprMethodID; @@ -124,19 +132,18 @@ static jmethodID restoreHandlerStacksMethodID; static jmethodID R_MakeExternalPtrMethodID; static jmethodID R_ExternalPtrAddrMethodID; static jmethodID R_ExternalPtrTagMethodID; -static jmethodID R_ExternalPtrProtMethodID; +static jmethodID R_ExternalPtrProtectedMethodID; static jmethodID R_SetExternalPtrAddrMethodID; static jmethodID R_SetExternalPtrTagMethodID; static jmethodID R_SetExternalPtrProtMethodID; -static jmethodID R_computeIdenticalMethodID; +static jmethodID R_compute_identicalMethodID; static jmethodID Rf_copyListMatrixMethodID; static jmethodID Rf_copyMatrixMethodID; static jmethodID Rf_nrowsMethodID; static jmethodID Rf_ncolsMethodID; static jclass CharSXPWrapperClass; -static jfieldID CharSXPWrapperContentsFieldID; jclass JNIUpCallsRFFIImplClass; jmethodID setCompleteMethodID; @@ -148,7 +155,7 @@ void init_internals(JNIEnv *env) { Rf_ScalarLogicalMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_ScalarLogical", "(I)Lcom/oracle/truffle/r/runtime/data/RLogicalVector;", 0); Rf_consMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_cons", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0); Rf_evalMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_eval", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0); - Rf_findfunMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_findfun", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0); + Rf_findFunMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_findFun", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0); Rf_defineVarMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_defineVar", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V", 0); Rf_findVarMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_findVar", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0); Rf_findVarInFrameMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_findVarInFrame", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0); @@ -158,18 +165,20 @@ void init_internals(JNIEnv *env) { Rf_isStringMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_isString", "(Ljava/lang/Object;)I", 0); Rf_isNullMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_isNull", "(Ljava/lang/Object;)I", 0); Rf_installMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_install", "(Ljava/lang/Object;)Ljava/lang/Object;", 0); + Rf_installCharMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_installChar", "(Ljava/lang/Object;)Ljava/lang/Object;", 0); Rf_warningMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_warning", "(Ljava/lang/Object;)V", 0); Rf_warningcallMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_warningcall", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0); Rf_errorMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_error", "(Ljava/lang/Object;)V", 0); - Rf_allocateVectorMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocateVector", "(II)Ljava/lang/Object;", 0); - Rf_allocateMatrixMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocateMatrix", "(III)Ljava/lang/Object;", 0); - Rf_allocateArrayMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocateArray", "(ILjava/lang/Object;)Ljava/lang/Object;", 0); + Rf_allocVectorMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocVector", "(II)Ljava/lang/Object;", 0); + Rf_allocMatrixMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocMatrix", "(III)Ljava/lang/Object;", 0); + Rf_allocArrayMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocArray", "(ILjava/lang/Object;)Ljava/lang/Object;", 0); Rf_duplicateMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_duplicate", "(Ljava/lang/Object;I)Ljava/lang/Object;", 0); - Rf_anyDuplicatedMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_anyDuplicated", "(Ljava/lang/Object;I)I", 0); - R_NewHashedEnvMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_NewHashedEnv", "(Lcom/oracle/truffle/r/runtime/env/REnvironment;I)Lcom/oracle/truffle/r/runtime/env/REnvironment;", 0); + Rf_any_duplicatedMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_any_duplicated", "(Ljava/lang/Object;I)I", 0); + R_NewHashedEnvMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_NewHashedEnv", "(Lcom/oracle/truffle/r/runtime/env/REnvironment;Ljava/lang/Object;)Lcom/oracle/truffle/r/runtime/env/REnvironment;", 0); Rf_classgetsMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_classgets", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0); RprintfMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rprintf", "(Ljava/lang/Object;)V", 0); R_do_MAKE_CLASS_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_do_MAKE_CLASS", "(Ljava/lang/Object;)Ljava/lang/Object;", 0); + R_do_new_object_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_do_new_object", "(Ljava/lang/Object;)Ljava/lang/Object;", 0); R_FindNamespaceMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_FindNamespace", "(Ljava/lang/Object;)Ljava/lang/Object;", 0); R_BindingIsLockedID = checkGetMethodID(env, UpCallsRFFIClass, "R_BindingIsLocked", "(Ljava/lang/Object;Ljava/lang/Object;)I", 0); Rf_GetOption1MethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_GetOption1", "(Ljava/lang/Object;)Ljava/lang/Object;", 0); @@ -200,6 +209,9 @@ void init_internals(JNIEnv *env) { STRING_ELT_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "STRING_ELT", "(Ljava/lang/Object;I)Ljava/lang/Object;", 0); VECTOR_ELT_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "VECTOR_ELT", "(Ljava/lang/Object;I)Ljava/lang/Object;", 0); LENGTH_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "LENGTH", "(Ljava/lang/Object;)I", 0); + R_do_slot_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_do_slot", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0); + R_do_slot_assign_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_do_slot_assign", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0); + R_MethodsNamespaceMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_MethodsNamespace", "()Ljava/lang/Object;", 0); Rf_asIntegerMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asInteger", "(Ljava/lang/Object;)I", 0); Rf_asRealMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asReal", "(Ljava/lang/Object;)D", 0); Rf_asCharMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asChar", "(Ljava/lang/Object;)Ljava/lang/Object;", 0); @@ -213,6 +225,8 @@ void init_internals(JNIEnv *env) { OBJECT_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "OBJECT", "(Ljava/lang/Object;)I", 0); DUPLICATE_ATTRIB_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "DUPLICATE_ATTRIB", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0); IS_S4_OBJECTMethodID = checkGetMethodID(env, UpCallsRFFIClass, "IS_S4_OBJECT", "(Ljava/lang/Object;)I", 0); + SET_S4_OBJECTMethodID = checkGetMethodID(env, UpCallsRFFIClass, "SET_S4_OBJECT", "(Ljava/lang/Object;)V", 0); + UNSET_S4_OBJECTMethodID = checkGetMethodID(env, UpCallsRFFIClass, "UNSET_S4_OBJECT", "(Ljava/lang/Object;)V", 0); R_tryEvalMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_tryEval", "(Ljava/lang/Object;Ljava/lang/Object;Z)Ljava/lang/Object;", 0); RDEBUGMethodID = checkGetMethodID(env, UpCallsRFFIClass, "RDEBUG", "(Ljava/lang/Object;)I", 0); SET_RDEBUGMethodID = checkGetMethodID(env, UpCallsRFFIClass, "SET_RDEBUG", "(Ljava/lang/Object;I)V", 0); @@ -231,15 +245,12 @@ void init_internals(JNIEnv *env) { R_MakeExternalPtrMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_MakeExternalPtr", "(JLjava/lang/Object;Ljava/lang/Object;)Lcom/oracle/truffle/r/runtime/data/RExternalPtr;", 0); R_ExternalPtrAddrMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ExternalPtrAddr", "(Ljava/lang/Object;)J", 0); R_ExternalPtrTagMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ExternalPtrTag", "(Ljava/lang/Object;)Ljava/lang/Object;", 0); - R_ExternalPtrProtMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ExternalPtrProt", "(Ljava/lang/Object;)Ljava/lang/Object;", 0); + R_ExternalPtrProtectedMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ExternalPtrProtected", "(Ljava/lang/Object;)Ljava/lang/Object;", 0); R_SetExternalPtrAddrMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_SetExternalPtrAddr", "(Ljava/lang/Object;J)V", 0); R_SetExternalPtrTagMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_SetExternalPtrTag", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0); - R_SetExternalPtrProtMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_SetExternalPtrProt", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0); + R_SetExternalPtrProtMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_SetExternalPtrProtected", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0); - CharSXPWrapperClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/CharSXPWrapper"); - CharSXPWrapperContentsFieldID = checkGetFieldID(env, CharSXPWrapperClass, "contents", "Ljava/lang/String;", 0); - - R_computeIdenticalMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_computeIdentical", "(Ljava/lang/Object;Ljava/lang/Object;I)I", 0); + R_compute_identicalMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_compute_identical", "(Ljava/lang/Object;Ljava/lang/Object;I)I", 0); Rf_copyListMatrixMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_copyListMatrix", "(Ljava/lang/Object;Ljava/lang/Object;I)V", 0); Rf_copyMatrixMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_copyMatrix", "(Ljava/lang/Object;Ljava/lang/Object;I)V", 0); Rf_nrowsMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_nrows", "(Ljava/lang/Object;)I", 0); @@ -247,21 +258,9 @@ void init_internals(JNIEnv *env) { // static JNI-specific methods JNIUpCallsRFFIImplClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jni/JNIUpCallsRFFIImpl"); - logNotCharSXPWrapperMethodID = checkGetMethodID(env, UpCallsRFFIClass, "logNotCharSXPWrapper", "(Ljava/lang/Object;)V", 1); - restoreHandlerStacksMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ToplevelExecRestoreErrorHandlerStacks", "(Ljava/lang/Object;)V", 1); - setCompleteMethodID = checkGetMethodID(env, UpCallsRFFIClass, "setComplete", "(Ljava/lang/Object;Z)V", 1); -} - -static jstring stringFromCharSXP(JNIEnv *thisenv, SEXP charsxp) { -#if VALIDATE_REFS - validateRef(thisenv, charsxp, "stringFromCharSXP"); - if (!(*thisenv)->IsInstanceOf(thisenv, charsxp, CharSXPWrapperClass)) { - - (*thisenv)->CallStaticVoidMethod(thisenv, JNIUpCallsRFFIImplClass, logNotCharSXPWrapperMethodID, charsxp); - fatalError("only CharSXPWrapper expected in stringFromCharSXP"); - } -#endif - return (*thisenv)->GetObjectField(thisenv, charsxp, CharSXPWrapperContentsFieldID); + restoreHandlerStacksMethodID = checkGetMethodID(env, JNIUpCallsRFFIImplClass, "R_ToplevelExecRestoreErrorHandlerStacks", "(Ljava/lang/Object;)V", 1); + setCompleteMethodID = checkGetMethodID(env, JNIUpCallsRFFIImplClass, "setComplete", "(Ljava/lang/Object;Z)V", 1); + logNotCharSXPWrapperMethodID = checkGetMethodID(env, JNIUpCallsRFFIImplClass, "logNotCharSXPWrapper", "(Ljava/lang/Object;)V", 1); } SEXP Rf_ScalarInteger(int value) { @@ -298,14 +297,14 @@ SEXP Rf_allocVector3(SEXPTYPE t, R_xlen_t len, R_allocator_t* allocator) { } TRACE(TARGpd, t, len); JNIEnv *thisenv = getEnv(); - SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_allocateVectorMethodID, t, len); + SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_allocVectorMethodID, t, len); return checkRef(thisenv, result); } SEXP Rf_allocArray(SEXPTYPE t, SEXP dims) { TRACE(TARGppd, t, dims); JNIEnv *thisenv = getEnv(); - SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_allocateArrayMethodID, t, dims); + SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_allocArrayMethodID, t, dims); return checkRef(thisenv, result); } @@ -316,7 +315,7 @@ SEXP Rf_alloc3DArray(SEXPTYPE t, int x, int y, int z) { SEXP Rf_allocMatrix(SEXPTYPE mode, int nrow, int ncol) { TRACE(TARGppd, mode, nrow, ncol); JNIEnv *thisenv = getEnv(); - SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_allocateMatrixMethodID, mode, nrow, ncol); + SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_allocMatrixMethodID, mode, nrow, ncol); return checkRef(thisenv, result); } @@ -365,7 +364,7 @@ SEXP Rf_eval(SEXP expr, SEXP env) { SEXP Rf_findFun(SEXP symbol, SEXP rho) { TRACE(TARGpp, symbol, rho); JNIEnv *thisenv = getEnv(); - SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_findfunMethodID, symbol, rho); + SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_findFunMethodID, symbol, rho); return checkRef(thisenv, result); } @@ -422,7 +421,7 @@ R_xlen_t Rf_any_duplicated(SEXP x, Rboolean from_last) { TRACE(TARGpd, x, from_last); if (!isVector(x)) error(_("'duplicated' applies only to vectors")); JNIEnv *thisenv = getEnv(); - return (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, Rf_anyDuplicatedMethodID, x, from_last); + return (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, Rf_any_duplicatedMethodID, x, from_last); } SEXP Rf_duplicated(SEXP x, Rboolean y) { @@ -453,29 +452,6 @@ Rboolean Rf_inherits(SEXP x, const char * klass) { return (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, Rf_inheritsMethodID, x, klazz); } -Rboolean Rf_isReal(SEXP x) { - return TYPEOF(x) == REALSXP; -} - -Rboolean Rf_isSymbol(SEXP x) { - return TYPEOF(x) == SYMSXP; -} - -Rboolean Rf_isComplex(SEXP x) { - return TYPEOF(x) == CPLXSXP; -} - -Rboolean Rf_isEnvironment(SEXP x) { - return TYPEOF(x) == ENVSXP; -} - -Rboolean Rf_isExpression(SEXP x) { - return TYPEOF(x) == EXPRSXP; -} - -Rboolean Rf_isLogical(SEXP x) { - return TYPEOF(x) == LGLSXP; -} Rboolean Rf_isObject(SEXP s) { unimplemented("Rf_isObject"); @@ -491,14 +467,14 @@ SEXP Rf_install(const char *name) { JNIEnv *thisenv = getEnv(); jstring string = (*thisenv)->NewStringUTF(thisenv, name); SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_installMethodID, string); + addGlobalRef(thisenv, result, 1); return checkRef(thisenv, result); } SEXP Rf_installChar(SEXP charsxp) { TRACE(TARGp, charsxp); JNIEnv *thisenv = getEnv(); - jstring string = stringFromCharSXP(thisenv, charsxp); - SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_installMethodID, string); + SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_installCharMethodID, charsxp); return checkRef(thisenv, result); } @@ -618,7 +594,6 @@ void Rf_error(const char *format, ...) { (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_errorMethodID, string); // just transfer back which will cleanup and exit the entire JNI call longjmp(*getErrorJmpBuf(), 1); - } void Rf_errorcall(SEXP x, const char *format, ...) { @@ -759,60 +734,6 @@ SEXP GetOption1(SEXP tag) return checkRef(thisenv, result); } -SEXP GetOption(SEXP tag, SEXP rho) -{ - return GetOption1(tag); -} - -int GetOptionCutoff(void) -{ - int w; - w = asInteger(GetOption1(install("deparse.cutoff"))); - if (w == NA_INTEGER || w <= 0) { - warning(_("invalid 'deparse.cutoff', used 60")); - w = 60; - } - return w; -} - -#define R_MIN_WIDTH_OPT 10 -#define R_MAX_WIDTH_OPT 10000 -#define R_MIN_DIGITS_OPT 0 -#define R_MAX_DIGITS_OPT 22 - -int GetOptionWidth(void) -{ - int w; - w = asInteger(GetOption1(install("width"))); - if (w < R_MIN_WIDTH_OPT || w > R_MAX_WIDTH_OPT) { - warning(_("invalid printing width, used 80")); - return 80; - } - return w; -} - -int GetOptionDigits(void) -{ - int d; - d = asInteger(GetOption1(install("digits"))); - if (d < R_MIN_DIGITS_OPT || d > R_MAX_DIGITS_OPT) { - warning(_("invalid printing digits, used 7")); - return 7; - } - return d; -} - -Rboolean Rf_GetOptionDeviceAsk(void) -{ - int ask; - ask = asLogical(GetOption1(install("device.ask.default"))); - if(ask == NA_LOGICAL) { - warning(_("invalid value for \"device.ask.default\", using FALSE")); - return FALSE; - } - return ask != 0; -} - void Rf_gsetVar(SEXP symbol, SEXP value, SEXP rho) { JNIEnv *thisenv = getEnv(); @@ -1079,7 +1000,7 @@ SEXP PRVALUE(SEXP x) { int PRSEEN(SEXP x) { JNIEnv *thisenv = getEnv(); - return (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, PRSEENMethodID, x); + return (int) (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, PRSEENMethodID, x); } void SET_PRSEEN(SEXP x, int v) { @@ -1101,7 +1022,7 @@ void SET_PRCODE(SEXP x, SEXP v) { int LENGTH(SEXP x) { TRACE(TARGp, x); JNIEnv *thisenv = getEnv(); - return (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, LENGTH_MethodID, x); + return (int) (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, LENGTH_MethodID, x); } int TRUELENGTH(SEXP x){ @@ -1220,9 +1141,8 @@ SEXP *STRING_PTR(SEXP x){ } -SEXP *VECTOR_PTR(SEXP x){ +SEXP * NORET VECTOR_PTR(SEXP x){ unimplemented("VECTOR_PTR"); - return NULL; } SEXP Rf_asChar(SEXP x){ @@ -1275,7 +1195,7 @@ double Rf_asReal(SEXP x) { } Rcomplex Rf_asComplex(SEXP x){ - unimplemented("Rf_asLogical"); + unimplemented("Rf_asComplex"); Rcomplex c; return c; } @@ -1337,44 +1257,14 @@ void DUPLICATE_ATTRIB(SEXP to, SEXP from){ (*thisenv)->CallVoidMethod(thisenv, UpCallsRFFIObject, DUPLICATE_ATTRIB_MethodID, to, from); } -char *dgettext(const char *domainname, const char *msgid) { - printf("dgettext: '%s'\n", msgid); - return (char*) msgid; -} - -char *libintl_dgettext(const char *domainname, const char *msgid) { - return dgettext(domainname, msgid); -} - -char *dngettext(const char *domainname, const char *msgid, const char * msgid_plural, unsigned long int n) { - printf("dngettext: singular - '%s' ; plural - '%s'\n", msgid, msgid_plural); - return (char*) (n == 1 ? msgid : msgid_plural); -} - const char *R_CHAR(SEXP charsxp) { TRACE("%s(%p)", charsxp); JNIEnv *thisenv = getEnv(); - jstring string = stringFromCharSXP(thisenv, charsxp); - char *copyChars = (char *) stringToChars(thisenv, string); + const char *copyChars = (const char *) getNativeArray(thisenv, charsxp, CHARSXP); TRACE(" %s(%s)\n", copyChars); return copyChars; } -void *DATAPTR(SEXP x) { - int type = TYPEOF(x); - if (type == INTSXP) { - return INTEGER(x); - } else if (type == REALSXP) { - return REAL(x); - } else if (type == LGLSXP) { - return LOGICAL(x); - } else { - printf("DATAPTR %d\n", type); - unimplemented("R_DATAPTR"); - return NULL; - } -} - void R_qsort_I (double *v, int *II, int i, int j) { unimplemented("R_qsort_I"); } @@ -1393,10 +1283,13 @@ int IS_S4_OBJECT(SEXP x) { } void SET_S4_OBJECT(SEXP x) { - unimplemented("SET_S4_OBJECT"); + JNIEnv *env = getEnv(); + (*env)->CallVoidMethod(env, UpCallsRFFIObject, SET_S4_OBJECTMethodID, x); } + void UNSET_S4_OBJECT(SEXP x) { - unimplemented("UNSET_S4_OBJECT"); + JNIEnv *env = getEnv(); + (*env)->CallVoidMethod(env, UpCallsRFFIObject, UNSET_S4_OBJECTMethodID, x); } Rboolean R_ToplevelExec(void (*fun)(void *), void *data) { @@ -1470,7 +1363,7 @@ Rboolean R_BindingIsLocked(SEXP sym, SEXP env) { } Rboolean R_BindingIsActive(SEXP sym, SEXP env) { - // TODO: for now, I belive all bindings are false + // TODO: for now, I believe all bindings are false return (Rboolean)0; } @@ -1547,7 +1440,7 @@ SEXP R_ExternalPtrTag(SEXP s) { SEXP R_ExternalPtrProt(SEXP s) { JNIEnv *thisenv = getEnv(); - SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, R_ExternalPtrProtMethodID, s); + SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, R_ExternalPtrProtectedMethodID, s); return checkRef(thisenv, result); } @@ -1611,11 +1504,17 @@ void R_RunWeakRefFinalizer(SEXP w) { } SEXP R_do_slot(SEXP obj, SEXP name) { - return unimplemented("R_do_slot"); + TRACE(TARGp, obj, name); + JNIEnv *thisenv = getEnv(); + SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, R_do_slot_MethodID, obj, name); + return checkRef(thisenv, result); } -SEXP R_do_slot_assign(SEXP obj, SEXP name, SEXP value) { - return unimplemented("R_do_slot_assign"); +SEXP R_do_slot_assign(SEXP obj, SEXP name, SEXP value) { // Same like R_set_slot + TRACE(TARGp, obj, name, value); + JNIEnv *thisenv = getEnv(); + SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, R_do_slot_assign_MethodID, obj, name, value); + return checkRef(thisenv, result); } int R_has_slot(SEXP obj, SEXP name) { @@ -1633,15 +1532,18 @@ SEXP R_getClassDef (const char *what) { } SEXP R_do_new_object(SEXP class_def) { - return unimplemented("R_do_new_object"); + JNIEnv *thisenv = getEnv(); + SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, R_do_new_object_MethodID, class_def); + return checkRef(thisenv, result); } -int R_check_class_and_super(SEXP x, const char **valid, SEXP rho) { - return (int) unimplemented("R_check_class_and_super"); +static SEXP jniGetMethodsNamespace() { + JNIEnv *thisenv = getEnv(); + return (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, R_MethodsNamespaceMethodID); } int R_check_class_etc (SEXP x, const char **valid) { - return (int) unimplemented("R_check_class_etc"); + return R_check_class_etc_helper(x, valid, jniGetMethodsNamespace); } SEXP R_PreserveObject(SEXP x) { @@ -1660,15 +1562,16 @@ void R_dot_Last(void) { Rboolean R_compute_identical(SEXP x, SEXP y, int flags) { JNIEnv *thisenv = getEnv(); - return (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, R_computeIdenticalMethodID, x, y, flags); + return (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, R_compute_identicalMethodID, x, y, flags); } void Rf_copyListMatrix(SEXP s, SEXP t, Rboolean byrow) { - JNIEnv *thisenv = getEnv(); + JNIEnv *thisenv = getEnv(); (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, Rf_copyListMatrixMethodID, s, t, byrow); } void Rf_copyMatrix(SEXP s, SEXP t, Rboolean byrow) { - JNIEnv *thisenv = getEnv(); + JNIEnv *thisenv = getEnv(); (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, Rf_copyMatrixMethodID, s, t, byrow); } + diff --git a/com.oracle.truffle.r.native/fficall/src/jni/call_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/call_rffi.c index 4ec83f1392613e02ef7b74b0b7a44aba2e34dd37..47ffc6ef39c9b9608027e0c8edaa93da6704d717 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/call_rffi.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/call_rffi.c @@ -33,6 +33,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_initialize(JNIEnv *env, jcla init_variables(env, initialValues); init_dynload(env); init_internals(env); + init_connections(env); init_rmath(env); init_random(env); init_parse(env); diff --git a/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c index 3a086352c9861398c6ba3cac6f83bdb1aa2edf36..daa89b365bfb54df08344acace2f4ef8e57b8686 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -137,6 +137,18 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dpotrf(JNIEnv *env return info; } +extern int dpotri_(char *uplo, int *n, double *a, int *lda, int *info); + +JNIEXPORT jint JNICALL +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dpotri(JNIEnv *env, jclass klass, + char uplo, int n, jdoubleArray ja, int lda) { + double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL); + int info; + dpotri_(&uplo, &n, a, &lda, &info); + (*env)->ReleasePrimitiveArrayCritical(env, ja, a, 0); + return info; +} + extern int dpstrf_(char *uplo, int *n, double *a, int *lda, int *piv, int *rank, double *tol, double *work, int *info); JNIEXPORT jint JNICALL diff --git a/com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c index 5b4f1bbbec39914f2a96a870e3f5d39824b03e23..c8964b9ee037f0e2ad27ab154cbe497ceee15ac9 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c @@ -5,7 +5,7 @@ * * Copyright (c) 1995, 1996 Robert Gentleman and Ross Ihaka * Copyright (c) 1997-2015, The R Core Team - * Copyright (c) 2016, Oracle and/or its affiliates + * Copyright (c) 2016, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -41,7 +41,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeCompile(JNIEnv *env, j const char *patternChars = (*env)->GetStringUTFChars(env, pattern, NULL); char *errorMessage; int errOffset; - void *pcre_result = pcre_compile(patternChars, options, &errorMessage, &errOffset, (char*) tables); + void *pcre_result = pcre_compile((char *) patternChars, options, &errorMessage, &errOffset, (char*) tables); jstring stringErrorMessage = NULL; if (pcre_result == NULL) { stringErrorMessage = (*env)->NewStringUTF(env, errorMessage); @@ -53,7 +53,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeCompile(JNIEnv *env, j JNIEXPORT jint JNICALL Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeGetCaptureCount(JNIEnv *env, jclass c, jlong code, jlong extra) { int captureCount; - int rc = pcre_fullinfo(code, extra, PCRE_INFO_CAPTURECOUNT, &captureCount); + int rc = pcre_fullinfo((void *)code, (void *)extra, PCRE_INFO_CAPTURECOUNT, &captureCount); return rc < 0 ? rc : captureCount; } @@ -63,15 +63,15 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeGetCaptureNames(JNIEnv int nameEntrySize; char* nameTable; int res; - res = pcre_fullinfo(code, extra, PCRE_INFO_NAMECOUNT, &nameCount); + res = pcre_fullinfo((void *) code, (void *) extra, PCRE_INFO_NAMECOUNT, &nameCount); if (res < 0) { return res; } - res = pcre_fullinfo(code, extra, PCRE_INFO_NAMEENTRYSIZE, &nameEntrySize); + res = pcre_fullinfo((void *) code, (void *) extra, PCRE_INFO_NAMEENTRYSIZE, &nameEntrySize); if (res < 0) { return res; } - res = pcre_fullinfo(code, extra, PCRE_INFO_NAMETABLE, &nameTable); + res = pcre_fullinfo((void *) code,(void *) extra, PCRE_INFO_NAMETABLE, &nameTable); if (res < 0) { return res; } @@ -91,7 +91,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeExec(JNIEnv *env, jcla int subjectLength = (*env)->GetStringUTFLength(env, subject); int* ovectorElems = (*env)->GetIntArrayElements(env, ovector, NULL); - int rc = pcre_exec(code, extra, subjectChars, subjectLength, startOffset, options, + int rc = pcre_exec((void *) code,(void *) extra, (char *) subjectChars, subjectLength, startOffset, options, ovectorElems, ovectorLen); (*env)->ReleaseIntArrayElements(env, ovector, ovectorElems, 0); (*env)->ReleaseStringUTFChars(env, subject, subjectChars); diff --git a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c index 03118d01c25eaf42c879226e0dfadf0a4476489a..9df3ebbeafedac00a00faa15d25b1209a8d7bf49 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c @@ -24,6 +24,8 @@ #include <string.h> #include <stdlib.h> #include <errno.h> +#include <assert.h> + /* * All calls pass through one of the call(N) methods in rfficall.c, which carry the JNIEnv value, @@ -42,8 +44,8 @@ static JNIEnv *curenv = NULL; FILE *traceFile = NULL; typedef struct globalRefTable_struct { - int permanent; - SEXP gref; // The jobject (SEXP) global ref + int permanent; + SEXP gref; // The jobject (SEXP) global ref } GlobalRefElem; #define CACHED_GLOBALREFS_INITIAL_SIZE 64 @@ -56,10 +58,10 @@ static int cachedGlobalRefsLength; // N.B. There are actually two levels to this as FastR // wraps, e.g., int[] in an RIntVector. typedef struct nativeArrayTable_struct { - SEXPTYPE type; - SEXP obj; // The jobject (SEXP) that data is derived from (e.g, RIntVector) - void *jArray; // the jarray corresponding to obj - void *data; // the (possibly) copied (or pinned) data from JNI GetXXXArrayElements + SEXPTYPE type; + SEXP obj; // The jobject (SEXP) that data is derived from (e.g, RIntVector) + void *jArray; // the jarray corresponding to obj + void *data; // the (possibly) copied (or pinned) data from JNI GetXXXArrayElements } NativeArrayElem; #define NATIVE_ARRAY_TABLE_INITIAL_SIZE 64 @@ -68,12 +70,58 @@ typedef struct nativeArrayTable_struct { static NativeArrayElem *nativeArrayTable; // hwm of nativeArrayTable static int nativeArrayTableHwm; +static int nativeArrayTableLastIndex; static int nativeArrayTableLength; -static void releaseNativeArray(JNIEnv *env, int index, int freedata); +static void releaseNativeArray(JNIEnv *env, int index); + +static jfieldID CharSXPWrapperContentsFieldID; +extern jmethodID logNotCharSXPWrapperMethodID; static int isEmbedded = 0; void setEmbedded() { - isEmbedded = 1; + isEmbedded = 1; +} + +#ifdef TRACE_ENABLED +// Helper for debugging purposes: prints out (into the trace file) the java +// class name for given SEXP +static void fastRInspect(JNIEnv *env, SEXP v) { + // this invokes getClass().getName() + jclass cls = (*env)->GetObjectClass(env, v); + jmethodID getClassMethodID = checkGetMethodID(env, cls, "getClass", "()Ljava/lang/Class;", 0); + jobject classObj = (*env)->CallObjectMethod(env, v, getClassMethodID); + jclass javaClassClass = (*env)->GetObjectClass(env, classObj); + jmethodID getNameMethodID = checkGetMethodID(env, javaClassClass, "getName", "()Ljava/lang/String;", 0); + jstring nameJString = (jstring)(*env)->CallObjectMethod(env, javaClassClass, getNameMethodID); + + // This gets us the C string + const char* result = (*env)->GetStringUTFChars(env, nameJString, NULL); + fprintf(traceFile, "fastRInspect(%p): %s\n", v, result); + + // Release the memory + (*env)->ReleaseStringUTFChars(env, nameJString, result); +} +#endif + +static int isValidJNIRef(JNIEnv *env, SEXP ref) { +#if VALIDATE_REFS + return (*env)->GetObjectRefType(env, ref) != JNIInvalidRefType; +#else + return TRUE; +#endif +} + +static jboolean fast_IsSameObject(jobject a, jobject b) { + // this takes some assumptions about jni handles, but it is much faster + void** pA = (void**) a; + void** pB = (void**) b; + if (pA == NULL && pB == NULL) { + return TRUE; + } else if (pA == NULL || pB == NULL) { + return FALSE; + } else { + return *pA == *pB; + } } // native down call depth, indexes nativeArrayTableHwmStack @@ -87,410 +135,454 @@ static jmp_buf* callErrorJmpBufTable[CALLDEPTH_STACK_SIZE]; void init_utils(JNIEnv *env, jobject upCallsInstance) { - curenv = env; - UpCallsRFFIClass = (*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, upCallsInstance)); - UpCallsRFFIObject = (*env)->NewGlobalRef(env, upCallsInstance); - if (TRACE_ENABLED && traceFile == NULL) { - if (!isEmbedded) { - traceFile = stdout; - } else { - jclass RFFIUtilsClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/RFFIUtils"); - jclass FileDescriptorClass = checkFindClass(env, "java/io/FileDescriptor"); - jmethodID getTraceFileDescriptorMethodID = checkGetMethodID(env, RFFIUtilsClass, "getTraceFileDescriptor", "()Ljava/io/FileDescriptor;", 1); - // ASSUMPTION: FileDescriptor has an "fd" field - jobject tfd = (*env)->CallStaticObjectMethod(env, RFFIUtilsClass, getTraceFileDescriptorMethodID); - jfieldID fdField = checkGetFieldID(env, FileDescriptorClass, "fd", "I", 0); - int fd = (*env)->GetIntField(env, tfd, fdField); - traceFile = fdopen(fd, "w"); - if (traceFile == NULL) { - fprintf(stderr, "%s, %d", "failed to fdopen trace file on JNI side\n", errno); - exit(1); - } - // no buffering - setvbuf(traceFile, (char*) NULL, _IONBF, 0); - } - } + curenv = env; + UpCallsRFFIClass = (*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, upCallsInstance)); + UpCallsRFFIObject = (*env)->NewGlobalRef(env, upCallsInstance); + if (TRACE_ENABLED && traceFile == NULL) { + if (!isEmbedded) { + traceFile = stdout; + } else { + jclass RFFIUtilsClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/RFFIUtils"); + jclass FileDescriptorClass = checkFindClass(env, "java/io/FileDescriptor"); + jmethodID getTraceFileDescriptorMethodID = checkGetMethodID(env, RFFIUtilsClass, "getTraceFileDescriptor", "()Ljava/io/FileDescriptor;", 1); + // ASSUMPTION: FileDescriptor has an "fd" field + jobject tfd = (*env)->CallStaticObjectMethod(env, RFFIUtilsClass, getTraceFileDescriptorMethodID); + jfieldID fdField = checkGetFieldID(env, FileDescriptorClass, "fd", "I", 0); + int fd = (*env)->GetIntField(env, tfd, fdField); + traceFile = fdopen(fd, "w"); + if (traceFile == NULL) { + fprintf(stderr, "%s, %d", "failed to fdopen trace file on JNI side\n", errno); + exit(1); + } + // no buffering + setvbuf(traceFile, (char*) NULL, _IONBF, 0); + } + } cachedGlobalRefs = calloc(CACHED_GLOBALREFS_INITIAL_SIZE, sizeof(GlobalRefElem)); cachedGlobalRefsLength = CACHED_GLOBALREFS_INITIAL_SIZE; cachedGlobalRefsHwm = 0; - nativeArrayTable = calloc(NATIVE_ARRAY_TABLE_INITIAL_SIZE, sizeof(NativeArrayElem)); - nativeArrayTableLength = NATIVE_ARRAY_TABLE_INITIAL_SIZE; - nativeArrayTableHwm = 0; + nativeArrayTable = calloc(NATIVE_ARRAY_TABLE_INITIAL_SIZE, sizeof(NativeArrayElem)); + nativeArrayTableLength = NATIVE_ARRAY_TABLE_INITIAL_SIZE; + nativeArrayTableHwm = 0; + + CharSXPWrapperClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/CharSXPWrapper"); + CharSXPWrapperContentsFieldID = checkGetFieldID(env, CharSXPWrapperClass, "contents", "Ljava/lang/String;", 0); } const char *stringToChars(JNIEnv *jniEnv, jstring string) { - // This is nasty: - // 1. the resulting character array has to be copied and zero-terminated. - // 2. It causes an (inevitable?) memory leak - jsize len = (*jniEnv)->GetStringUTFLength(jniEnv, string); - const char *stringChars = (*jniEnv)->GetStringUTFChars(jniEnv, string, NULL); - char *copyChars = malloc(len + 1); - memcpy(copyChars, stringChars, len); - copyChars[len] = 0; - return copyChars; + // This is nasty: + // 1. the resulting character array has to be copied and zero-terminated. + // 2. It causes an (inevitable?) memory leak + jsize len = (*jniEnv)->GetStringUTFLength(jniEnv, string); + const char *stringChars = (*jniEnv)->GetStringUTFChars(jniEnv, string, NULL); + char *copyChars = malloc(len + 1); + memcpy(copyChars, stringChars, len); + copyChars[len] = 0; + return copyChars; } void callEnter(JNIEnv *env, jmp_buf *jmpbuf) { - setEnv(env); - //printf("callEnter: callDepth %d, jmpbufptr %p\n", callDepth, jmpbuf); - callErrorJmpBufTable[callDepth] = jmpbuf; - if (callDepth >= CALLDEPTH_STACK_SIZE) { - fatalError("call stack overflow\n"); - } - nativeArrayTableHwmStack[callDepth] = nativeArrayTableHwm; - callDepth++; + setEnv(env); + //printf("callEnter: callDepth %d, jmpbufptr %p\n", callDepth, jmpbuf); + callErrorJmpBufTable[callDepth] = jmpbuf; + if (callDepth >= CALLDEPTH_STACK_SIZE) { + fatalError("call stack overflow\n"); + } + nativeArrayTableHwmStack[callDepth] = nativeArrayTableHwm; + callDepth++; } jmp_buf *getErrorJmpBuf() { - // printf("getErrorJmpBuf: callDepth %d, jmpbufptr %p\n", callDepth, callErrorJmpBufTable[callDepth - 1]); - return callErrorJmpBufTable[callDepth - 1]; + // printf("getErrorJmpBuf: callDepth %d, jmpbufptr %p\n", callDepth, callErrorJmpBufTable[callDepth - 1]); + return callErrorJmpBufTable[callDepth - 1]; } void callExit(JNIEnv *env) { - int oldHwm = nativeArrayTableHwmStack[callDepth - 1]; - for (int i = oldHwm; i < nativeArrayTableHwm; i++) { - releaseNativeArray(env, i, 1); - } - nativeArrayTableHwm = oldHwm; - callDepth--; + int oldHwm = nativeArrayTableHwmStack[callDepth - 1]; + for (int i = oldHwm; i < nativeArrayTableHwm; i++) { + releaseNativeArray(env, i); + } + nativeArrayTableHwm = oldHwm; + callDepth--; } void invalidateNativeArray(JNIEnv *env, SEXP oldObj) { - for (int i = 0; i < nativeArrayTableHwm; i++) { - NativeArrayElem cv = nativeArrayTable[i]; - if ((*env)->IsSameObject(env, cv.obj, oldObj)) { + assert(isValidJNIRef(env, oldObj)); + for (int i = 0; i < nativeArrayTableHwm; i++) { + NativeArrayElem cv = nativeArrayTable[i]; + if (fast_IsSameObject(cv.obj, oldObj)) { #if TRACE_NATIVE_ARRAYS - fprintf(traceFile, "invalidateNativeArray(%p): found\n", oldObj); + fprintf(traceFile, "invalidateNativeArray(%p): found\n", oldObj); #endif - releaseNativeArray(env, i, 1); - nativeArrayTable[i].obj = NULL; - } - } + releaseNativeArray(env, i); + nativeArrayTable[i].obj = NULL; + } + } #if TRACE_NATIVE_ARRAYS - fprintf(traceFile, "invalidateNativeArray(%p): not found\n", oldObj); + fprintf(traceFile, "invalidateNativeArray(%p): not found\n", oldObj); #endif } void updateNativeArrays(JNIEnv *env) { - int oldHwm = nativeArrayTableHwmStack[callDepth - 1]; - for (int i = oldHwm; i < nativeArrayTableHwm; i++) { - releaseNativeArray(env, i, 0); - } + // We just release the arrays, the up call may change their contents in the R world, + // so we cannot re-use the native buffers which may be out of sync + int oldHwm = nativeArrayTableHwmStack[callDepth - 1]; + for (int i = oldHwm; i < nativeArrayTableHwm; i++) { + releaseNativeArray(env, i); + } } static void *findNativeArray(JNIEnv *env, SEXP x) { - int i; - for (i = 0; i < nativeArrayTableHwm; i++) { - NativeArrayElem cv = nativeArrayTable[i]; - if (cv.obj != NULL) { - if ((*env)->IsSameObject(env, cv.obj, x)) { - void *data = cv.data; + if (nativeArrayTableLastIndex < nativeArrayTableHwm) { + NativeArrayElem cv = nativeArrayTable[nativeArrayTableLastIndex]; + if (cv.obj != NULL && (cv.obj == x || fast_IsSameObject(cv.obj, x))) { + void *data = cv.data; #if TRACE_NATIVE_ARRAYS - fprintf(traceFile, "findNativeArray(%p): found %p\n", x, data); + fprintf(traceFile, "findNativeArray(%p): found %p (cached)\n", x, data); #endif - return data; - } - } - } + return data; + } + } + int i; + assert(isValidJNIRef(env, x)); + for (i = 0; i < nativeArrayTableHwm; i++) { + NativeArrayElem cv = nativeArrayTable[i]; + if (cv.obj != NULL) { + assert(isValidJNIRef(env, cv.obj)); + if (fast_IsSameObject(cv.obj, x)) { + nativeArrayTableLastIndex = i; + void *data = cv.data; #if TRACE_NATIVE_ARRAYS - fprintf(traceFile, "findNativeArray(%p): not found\n", x); + fprintf(traceFile, "findNativeArray(%p): found %p\n", x, data); #endif - return NULL; + return data; + } + } + } +#if TRACE_NATIVE_ARRAYS + fprintf(traceFile, "findNativeArray(%p): not found\n", x); +#endif + return NULL; } static void addNativeArray(JNIEnv *env, SEXP x, SEXPTYPE type, void *jArray, void *data) { #if TRACE_NATIVE_ARRAYS - fprintf(traceFile, "addNativeArray(x=%p, t=%p, ix=%d)\n", x, data, nativeArrayTableHwm); + fprintf(traceFile, "addNativeArray(x=%p, t=%p, ix=%d)\n", x, data, nativeArrayTableHwm); #endif - // check for overflow - if (nativeArrayTableHwm >= nativeArrayTableLength) { - int newLength = 2 * nativeArrayTableLength; - NativeArrayElem *newnativeArrayTable = calloc(newLength, sizeof(NativeArrayElem)); - if (newnativeArrayTable == NULL) { - fatalError("FFI copied vectors table expansion failure"); - } - memcpy(newnativeArrayTable, nativeArrayTable, nativeArrayTableLength * sizeof(NativeArrayElem)); - free(nativeArrayTable); - nativeArrayTable = newnativeArrayTable; - nativeArrayTableLength = newLength; - } - nativeArrayTable[nativeArrayTableHwm].obj = x; - nativeArrayTable[nativeArrayTableHwm].data = data; - nativeArrayTable[nativeArrayTableHwm].type = type; - nativeArrayTable[nativeArrayTableHwm].jArray = jArray; - nativeArrayTableHwm++; + // check for overflow + if (nativeArrayTableHwm >= nativeArrayTableLength) { + int newLength = 2 * nativeArrayTableLength; + NativeArrayElem *newnativeArrayTable = calloc(newLength, sizeof(NativeArrayElem)); + if (newnativeArrayTable == NULL) { + fatalError("FFI copied vectors table expansion failure"); + } + memcpy(newnativeArrayTable, nativeArrayTable, nativeArrayTableLength * sizeof(NativeArrayElem)); + free(nativeArrayTable); + nativeArrayTable = newnativeArrayTable; + nativeArrayTableLength = newLength; + } + nativeArrayTable[nativeArrayTableHwm].obj = x; + nativeArrayTable[nativeArrayTableHwm].data = data; + nativeArrayTable[nativeArrayTableHwm].type = type; + nativeArrayTable[nativeArrayTableHwm].jArray = jArray; + nativeArrayTableHwm++; } void *getNativeArray(JNIEnv *thisenv, SEXP x, SEXPTYPE type) { - void *data = findNativeArray(thisenv, x); - jboolean isCopy; - if (data == NULL) { - jarray jArray; - switch (type) { - case INTSXP: { - jintArray intArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, INTEGER_MethodID, x); - int len = (*thisenv)->GetArrayLength(thisenv, intArray); - data = (*thisenv)->GetIntArrayElements(thisenv, intArray, &isCopy); - jArray = intArray; - break; - } - - case REALSXP: { - jdoubleArray doubleArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, REAL_MethodID, x); - int len = (*thisenv)->GetArrayLength(thisenv, doubleArray); - data = (*thisenv)->GetDoubleArrayElements(thisenv, doubleArray, &isCopy); - jArray = doubleArray; - break; - } - - case RAWSXP: { - jbyteArray byteArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, RAW_MethodID, x); - int len = (*thisenv)->GetArrayLength(thisenv, byteArray); - data = (*thisenv)->GetByteArrayElements(thisenv, byteArray, &isCopy); - jArray = byteArray; - break; - } - - case LGLSXP: { - // Special treatment becuase R FFI wants int* and FastR represents using byte[] - jbyteArray byteArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, LOGICAL_MethodID, x); - int len = (*thisenv)->GetArrayLength(thisenv, byteArray); - jbyte* internalData = (*thisenv)->GetByteArrayElements(thisenv, byteArray, &isCopy); - int* idata = malloc(len * sizeof(int)); - for (int i = 0; i < len; i++) { - char value = internalData[i]; - idata[i] = value == 0 ? FALSE : value == 1 ? TRUE : NA_INTEGER; - } - (*thisenv)->ReleaseByteArrayElements(thisenv, byteArray, internalData, JNI_ABORT); - jArray = byteArray; - data = idata; - break; - } - - default: - fatalError("getNativeArray: unexpected type"); - - } - addNativeArray(thisenv, x, type, jArray, data); - } - return data; + void *data = findNativeArray(thisenv, x); + jboolean isCopy; + if (data == NULL) { + jarray jArray; + switch (type) { + case INTSXP: { + jintArray intArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, INTEGER_MethodID, x); + int len = (*thisenv)->GetArrayLength(thisenv, intArray); + data = (*thisenv)->GetIntArrayElements(thisenv, intArray, &isCopy); + jArray = intArray; + break; + } + + case REALSXP: { + jdoubleArray doubleArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, REAL_MethodID, x); + int len = (*thisenv)->GetArrayLength(thisenv, doubleArray); + data = (*thisenv)->GetDoubleArrayElements(thisenv, doubleArray, &isCopy); + jArray = doubleArray; + break; + } + + case RAWSXP: { + jbyteArray byteArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, RAW_MethodID, x); + int len = (*thisenv)->GetArrayLength(thisenv, byteArray); + data = (*thisenv)->GetByteArrayElements(thisenv, byteArray, &isCopy); + jArray = byteArray; + break; + } + + case LGLSXP: { + // Special treatment because R FFI wants int* and FastR represents using byte[] + jbyteArray byteArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, LOGICAL_MethodID, x); + int len = (*thisenv)->GetArrayLength(thisenv, byteArray); + jbyte* internalData = (*thisenv)->GetByteArrayElements(thisenv, byteArray, &isCopy); + int* idata = malloc(len * sizeof(int)); + for (int i = 0; i < len; i++) { + char value = internalData[i]; + idata[i] = value == 0 ? FALSE : value == 1 ? TRUE : NA_INTEGER; + } + (*thisenv)->ReleaseByteArrayElements(thisenv, byteArray, internalData, JNI_ABORT); + jArray = byteArray; + data = idata; + break; + } + + case CHARSXP: { + jstring string = stringFromCharSXP(thisenv, x); + data = (void *) stringToChars(thisenv, string); + jArray = string; + break; + } + + default: + fatalError("getNativeArray: unexpected type"); + + } + addNativeArray(thisenv, x, type, jArray, data); + } + return data; } -static void releaseNativeArray(JNIEnv *env, int i, int freedata) { - NativeArrayElem cv = nativeArrayTable[i]; +static void releaseNativeArray(JNIEnv *env, int i) { + NativeArrayElem cv = nativeArrayTable[i]; #if TRACE_NATIVE_ARRAYS fprintf(traceFile, "releaseNativeArray(x=%p, ix=%d, freedata=%d)\n", cv.obj, i, freedata); #endif - if (cv.obj != NULL) { - jboolean complete = JNI_FALSE; // pessimal - switch (cv.type) { - case INTSXP: { - jintArray intArray = (jintArray) cv.jArray; - (*env)->ReleaseIntArrayElements(env, intArray, (jint *)cv.data, freedata ? 0 : JNI_COMMIT); - break; - } - - case LGLSXP: { - // for LOGICAL, we need to convert back to 1-byte elements - jintArray byteArray = (jbyteArray) cv.jArray; - int len = (*env)->GetArrayLength(env, byteArray); - jbyte* internalData = (*env)->GetByteArrayElements(env, byteArray, NULL); - int* data = (int*) cv.data; - complete = JNI_TRUE; // since we going to look at each element anyway - for (int i = 0; i < len; i++) { - int isNA = data[i] == NA_INTEGER ? JNI_TRUE : JNI_FALSE; - if (isNA) { - internalData[i] = 255; - complete = JNI_FALSE; - } else { - internalData[i] = (jbyte) data[i]; - } - - } - (*env)->ReleaseByteArrayElements(env, byteArray, internalData, 0); - if (freedata){ - free(data); // was malloc'ed in addNativeArray + if (cv.obj != NULL) { + assert(isValidJNIRef(env, cv.obj)); + jboolean complete = JNI_FALSE; // pessimal + switch (cv.type) { + case INTSXP: { + jintArray intArray = (jintArray) cv.jArray; + (*env)->ReleaseIntArrayElements(env, intArray, (jint *)cv.data, 0); + break; + } + + case LGLSXP: { + // for LOGICAL, we need to convert back to 1-byte elements + jintArray byteArray = (jbyteArray) cv.jArray; + int len = (*env)->GetArrayLength(env, byteArray); + jbyte* internalData = (*env)->GetByteArrayElements(env, byteArray, NULL); + int* data = (int*) cv.data; + complete = JNI_TRUE; // since we going to look at each element anyway + for (int i = 0; i < len; i++) { + int isNA = data[i] == NA_INTEGER ? JNI_TRUE : JNI_FALSE; + if (isNA) { + internalData[i] = 255; + complete = JNI_FALSE; + } else { + internalData[i] = (jbyte) data[i]; + } + } - break; - } - - case REALSXP: { - jdoubleArray doubleArray = (jdoubleArray) cv.jArray; - (*env)->ReleaseDoubleArrayElements(env, doubleArray, (jdouble *)cv.data, freedata ? 0 : JNI_COMMIT); - break; - - } - - case RAWSXP: { - jbyteArray byteArray = (jbyteArray) cv.jArray; - (*env)->ReleaseByteArrayElements(env, byteArray, (jbyte *)cv.data, freedata ? 0 : JNI_COMMIT); - break; - - } - default: - fatalError("releaseNativeArray type"); - } - // update complete status - (*env)->CallStaticVoidMethod(env, JNIUpCallsRFFIImplClass, setCompleteMethodID, cv.obj, complete); - - if (freedata) { - // free up the slot - cv.obj = NULL; + (*env)->ReleaseByteArrayElements(env, byteArray, internalData, 0); + free(data); // was malloc'ed in addNativeArray + break; } - } + + case REALSXP: { + jdoubleArray doubleArray = (jdoubleArray) cv.jArray; + (*env)->ReleaseDoubleArrayElements(env, doubleArray, (jdouble *)cv.data, 0); + break; + + } + + case RAWSXP: { + jbyteArray byteArray = (jbyteArray) cv.jArray; + (*env)->ReleaseByteArrayElements(env, byteArray, (jbyte *)cv.data, 0); + break; + + } + + case CHARSXP: { + jstring string = (jstring) cv.jArray; + (*env)->ReleaseStringUTFChars(env, string, (const char *)cv.data); + break; + + } + default: + fatalError("releaseNativeArray type"); + } + // update complete status + (*env)->CallStaticVoidMethod(env, JNIUpCallsRFFIImplClass, setCompleteMethodID, cv.obj, complete); + + // free up the slot + nativeArrayTable[i].obj = NULL; + } } static SEXP findCachedGlobalRef(JNIEnv *env, SEXP obj) { - for (int i = 0; i < cachedGlobalRefsHwm; i++) { - GlobalRefElem elem = cachedGlobalRefs[i]; - if (elem.gref == NULL) { - continue; - } - if ((*env)->IsSameObject(env, elem.gref, obj)) { + // TODO: this assert fails in test RFFI: assert(isValidJNIRef(env, obj)); + for (int i = 0; i < cachedGlobalRefsHwm; i++) { + GlobalRefElem elem = cachedGlobalRefs[i]; + if (elem.gref == NULL) { + continue; + } + if (fast_IsSameObject(elem.gref, obj)) { #if TRACE_REF_CACHE - fprintf(traceFile, "gref: cache hit: %d\n", i); + fprintf(traceFile, "gref: cache hit: %d\n", i); #endif - return elem.gref; - } - } - return NULL; + return elem.gref; + } + } + return NULL; } SEXP addGlobalRef(JNIEnv *env, SEXP obj, int permanent) { - SEXP gref; - if (cachedGlobalRefsHwm >= cachedGlobalRefsLength) { - int newLength = cachedGlobalRefsLength * 2; + SEXP gref; + assert(isValidJNIRef(env, obj)); + if (cachedGlobalRefsHwm >= cachedGlobalRefsLength) { + int newLength = cachedGlobalRefsLength * 2; #if TRACE_REF_CACHE - fprintf(traceFile, "gref: extending table to %d\n", newLength); + fprintf(traceFile, "gref: extending table to %d\n", newLength); #endif - SEXP newCachedGlobalRefs = calloc(newLength, sizeof(GlobalRefElem)); - if (newCachedGlobalRefs == NULL) { - fatalError("FFI global refs table expansion failure"); - } - memcpy(newCachedGlobalRefs, cachedGlobalRefs, cachedGlobalRefsLength * sizeof(GlobalRefElem)); - free(cachedGlobalRefs); - cachedGlobalRefs = newCachedGlobalRefs; - cachedGlobalRefsLength = newLength; - } - gref = (*env)->NewGlobalRef(env, obj); - cachedGlobalRefs[cachedGlobalRefsHwm].gref = gref; - cachedGlobalRefs[cachedGlobalRefsHwm].permanent = permanent; + SEXP newCachedGlobalRefs = calloc(newLength, sizeof(GlobalRefElem)); + if (newCachedGlobalRefs == NULL) { + fatalError("FFI global refs table expansion failure"); + } + memcpy(newCachedGlobalRefs, cachedGlobalRefs, cachedGlobalRefsLength * sizeof(GlobalRefElem)); + free(cachedGlobalRefs); + cachedGlobalRefs = newCachedGlobalRefs; + cachedGlobalRefsLength = newLength; + } + gref = (*env)->NewGlobalRef(env, obj); + cachedGlobalRefs[cachedGlobalRefsHwm].gref = gref; + cachedGlobalRefs[cachedGlobalRefsHwm].permanent = permanent; #if TRACE_REF_CACHE - fprintf(traceFile, "gref: add: index %d, ref %p\n", cachedGlobalRefsHwm), gref; + fprintf(traceFile, "gref: add: index %d, ref %p\n", cachedGlobalRefsHwm, gref); #endif - cachedGlobalRefsHwm++; - return gref; + cachedGlobalRefsHwm++; + return gref; } SEXP checkRef(JNIEnv *env, SEXP obj) { - SEXP gref = findCachedGlobalRef(env, obj); - TRACE(TARGpp, obj, gref); - if (gref == NULL) { - return obj; - } else { - return gref; - } + SEXP gref = findCachedGlobalRef(env, obj); + TRACE(TARGpp, obj, gref); + if (gref == NULL) { + return obj; + } else { + return gref; + } } SEXP createGlobalRef(JNIEnv *env, SEXP obj, int permanent) { - SEXP gref = findCachedGlobalRef(env, obj); - if (gref == NULL) { - gref = addGlobalRef(env, obj, permanent); - } - return gref; + SEXP gref = findCachedGlobalRef(env, obj); + if (gref == NULL) { + gref = addGlobalRef(env, obj, permanent); + } + return gref; } void releaseGlobalRef(JNIEnv *env, SEXP obj) { - for (int i = 0; i < cachedGlobalRefsHwm; i++) { - GlobalRefElem elem = cachedGlobalRefs[i]; - if (elem.gref == NULL || elem.permanent) { - continue; - } - if ((*env)->IsSameObject(env, elem.gref, obj)) { + for (int i = 0; i < cachedGlobalRefsHwm; i++) { + GlobalRefElem elem = cachedGlobalRefs[i]; + if (elem.gref == NULL || elem.permanent) { + continue; + } + if (fast_IsSameObject(elem.gref, obj)) { #if TRACE_REF_CACHE - fprintf(traceFile, "gref: release: index %d, gref: %p\n", i, elem.gref); + fprintf(traceFile, "gref: release: index %d, gref: %p\n", i, elem.gref); #endif - (*env)->DeleteGlobalRef(env, elem.gref); - cachedGlobalRefs[i].gref = NULL; - } - } + (*env)->DeleteGlobalRef(env, elem.gref); + cachedGlobalRefs[i].gref = NULL; + } + } } void validateRef(JNIEnv *env, SEXP x, const char *msg) { - jobjectRefType t = (*env)->GetObjectRefType(env, x); - if (t == JNIInvalidRefType) { - char buf[1000]; - sprintf(buf, "%s %p", msg,x); - fatalError(buf); - } +#ifdef VALIDATE_REFS + jobjectRefType t = (*env)->GetObjectRefType(env, x); + if (t == JNIInvalidRefType) { + char buf[1000]; + sprintf(buf, "%s %p", msg,x); + fatalError(buf); + } +#endif } JNIEnv *getEnv() { -// fprintf(traceFile, "getEnv()=%p\n", curenv); - return curenv; +// fprintf(traceFile, "getEnv()=%p\n", curenv); + return curenv; } void setEnv(JNIEnv *env) { -// printf("setEnv(%p)\n", env); - curenv = env; +// printf("setEnv(%p)\n", env); + curenv = env; } void *unimplemented(char *msg) { - JNIEnv *thisenv = getEnv(); - char buf[1024]; - strcpy(buf, "unimplemented "); - strcat(buf, msg); - (*thisenv)->FatalError(thisenv, buf); - // to keep compiler happy - return NULL; + JNIEnv *thisenv = getEnv(); + char buf[1024]; + strcpy(buf, "unimplemented "); + strcat(buf, msg); + (*thisenv)->FatalError(thisenv, buf); } void fatalError(char *msg) { - JNIEnv *thisenv = getEnv(); - (*thisenv)->FatalError(thisenv, msg); + JNIEnv *thisenv = getEnv(); + (*thisenv)->FatalError(thisenv, msg); } // Class/method search jclass checkFindClass(JNIEnv *env, const char *name) { - jclass klass = (*env)->FindClass(env, name); - if (klass == NULL) { - char buf[1024]; - strcpy(buf, "failed to find class "); - strcat(buf, name); - (*env)->FatalError(env, buf); - } - return (*env)->NewGlobalRef(env, klass); + jclass klass = (*env)->FindClass(env, name); + if (klass == NULL) { + char buf[1024]; + strcpy(buf, "failed to find class "); + strcat(buf, name); + (*env)->FatalError(env, buf); + } + return (*env)->NewGlobalRef(env, klass); } jmethodID checkGetMethodID(JNIEnv *env, jclass klass, const char *name, const char *sig, int isStatic) { - jmethodID methodID = isStatic ? (*env)->GetStaticMethodID(env, klass, name, sig) : (*env)->GetMethodID(env, klass, name, sig); - if (methodID == NULL) { - char buf[1024]; - strcpy(buf, "failed to find "); - strcat(buf, isStatic ? "static" : "instance"); - strcat(buf, " method "); - strcat(buf, name); - strcat(buf, "("); - strcat(buf, sig); - strcat(buf, ")"); - (*env)->FatalError(env, buf); - } - return methodID; + jmethodID methodID = isStatic ? (*env)->GetStaticMethodID(env, klass, name, sig) : (*env)->GetMethodID(env, klass, name, sig); + if (methodID == NULL) { + char buf[1024]; + strcpy(buf, "failed to find "); + strcat(buf, isStatic ? "static" : "instance"); + strcat(buf, " method "); + strcat(buf, name); + strcat(buf, "("); + strcat(buf, sig); + strcat(buf, ")"); + (*env)->FatalError(env, buf); + } + return methodID; } jfieldID checkGetFieldID(JNIEnv *env, jclass klass, const char *name, const char *sig, int isStatic) { - jfieldID fieldID = isStatic ? (*env)->GetStaticFieldID(env, klass, name, sig) : (*env)->GetFieldID(env, klass, name, sig); - if (fieldID == NULL) { - char buf[1024]; - strcpy(buf, "failed to find "); - strcat(buf, isStatic ? "static" : "instance"); - strcat(buf, " field "); - strcat(buf, name); - strcat(buf, "("); - strcat(buf, sig); - strcat(buf, ")"); - (*env)->FatalError(env, buf); + jfieldID fieldID = isStatic ? (*env)->GetStaticFieldID(env, klass, name, sig) : (*env)->GetFieldID(env, klass, name, sig); + if (fieldID == NULL) { + char buf[1024]; + strcpy(buf, "failed to find "); + strcat(buf, isStatic ? "static" : "instance"); + strcat(buf, " field "); + strcat(buf, name); + strcat(buf, "("); + strcat(buf, sig); + strcat(buf, ")"); + (*env)->FatalError(env, buf); + } + return fieldID; +} + +jstring stringFromCharSXP(JNIEnv *thisenv, SEXP charsxp) { +#if VALIDATE_REFS + validateRef(thisenv, charsxp, "stringFromCharSXP"); + if (!(*thisenv)->IsInstanceOf(thisenv, charsxp, CharSXPWrapperClass)) { + + (*thisenv)->CallStaticVoidMethod(thisenv, JNIUpCallsRFFIImplClass, logNotCharSXPWrapperMethodID, charsxp); + fatalError("only CharSXPWrapper expected in stringFromCharSXP"); } - return fieldID; +#endif + return (*thisenv)->GetObjectField(thisenv, charsxp, CharSXPWrapperContentsFieldID); } diff --git a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h index c86fc4bc15d69e15f9cb22bc70ced2a0d96676ad..91bd2d985dbb01555cf035768c4fbae852351c25 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h +++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h @@ -29,8 +29,9 @@ #include <limits.h> #include <Rinternals.h> #include <setjmp.h> +#include <Connections.h> -#define VALIDATE_REFS 1 +#define VALIDATE_REFS 0 JNIEnv *getEnv(); void setEnv(JNIEnv *env); @@ -40,9 +41,9 @@ jmethodID checkGetMethodID(JNIEnv *env, jclass klass, const char *name, const ch jfieldID checkGetFieldID(JNIEnv *env, jclass klass, const char *name, const char *sig, int isStatic); // use for an unimplemented API function -void *unimplemented(char *msg); +void *unimplemented(char *msg) __attribute__((noreturn)); // use for any fatal error -void fatalError(char *msg); +void fatalError(char *msg) __attribute__((noreturn)); // makes a call to the VM with x as an argument (for debugger validation) void validate(SEXP x); // checks x against the list of global JNI refs, returning the global version if x matches (IsSameObject) @@ -72,6 +73,8 @@ void *getNativeArray(JNIEnv *env, SEXP x, SEXPTYPE type); // Rare case where an operation changes the internal // data and thus the old C array should be invalidated void invalidateNativeArray(JNIEnv *env, SEXP oldObj); +// Should be called before up calling to arbitrary code, e.g. Rf_eval, +// to copy back the arrays into their Java counterparts void updateNativeArrays(JNIEnv *env); SEXP addGlobalRef(JNIEnv *env, SEXP obj, int permanent); @@ -85,6 +88,7 @@ void init_random(JNIEnv *env); void init_parse(JNIEnv *env); void init_pcre(JNIEnv *env); void init_c(JNIEnv *env); +void init_connections(JNIEnv *env); void setEmbedded(void); @@ -119,8 +123,10 @@ extern FILE *traceFile; #define _(Source) (Source) // convert a string into a char* +jstring stringFromCharSXP(JNIEnv *thisenv, SEXP charsxp); const char *stringToChars(JNIEnv *jniEnv, jstring string); + extern jmethodID INTEGER_MethodID; extern jmethodID LOGICAL_MethodID; extern jmethodID REAL_MethodID; diff --git a/com.oracle.truffle.r.native/fficall/src/jni/variables.c b/com.oracle.truffle.r.native/fficall/src/jni/variables.c index cbab66f68fde80d60e08d77d7956910c89d45001..c66739f886fa1eb5d9f4820d5b4666255645367e 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/variables.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/variables.c @@ -149,7 +149,8 @@ char *FASTR_R_TempDir() { Rboolean FASTR_R_Interactive() { JNIEnv *env = getEnv(); - CTXT res = (*env)->CallObjectMethod(env, UpCallsRFFIObject, R_InteractiveMethodID); + int res = (int) (*env)->CallObjectMethod(env, UpCallsRFFIObject, R_InteractiveMethodID); + return (Rboolean) res; } SEXP FASTR_R_EmptyEnv() { diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Makefile b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1d14ab2e86559cfad078f88b6148631c77925ad8 --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Makefile @@ -0,0 +1,63 @@ +# +# 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 +# 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. +# + +ifneq ($(MAKECMDGOALS),clean) +include $(TOPDIR)/platform.mk +endif + +.PHONY: all clean + +# location of compiled code (.o files) +OBJ = ../../lib + +C_HDRS := $(wildcard *.h) + +C_SOURCES = $(wildcard *.c) +C_OBJECTS := $(patsubst %.c,$(OBJ)/%.o,$(C_SOURCES)) +#$(info C_OBJECTS=$(C_OBJECTS)) + +FFI_INCLUDES = -I$(TOPDIR)/include -I$(TOPDIR)/include/R_ext +#NFI_INCLUDES is set in environment (by mx) +LOCAL_INCLUDES = -I . -I $(abspath ../include) -I $(abspath ../common) + +INCLUDES := $(LOCAL_INCLUDES) $(FFI_INCLUDES) $(NFI_INCLUDES) + +# uncomment to see exactly where headers are being read from +#CFLAGS := $(CFLAGS) -H + +all: Makefile $(C_OBJECTS) + +$(C_OBJECTS): | $(OBJ) + +$(OBJ): + mkdir -p $(OBJ) + +$(OBJ)/%.o: %.c $(TOPDIR)/include/Rinternals.h rffi_callbacksindex.h $(C_HDRS) + $(CC) $(CFLAGS) $(INCLUDES) -I../variable_defs -c $< -o $@ + +# for debugging, to see what's really being compiled +$(OBJ)/%.E: %.c $(TOPDIR)/include/Rinternals.h + $(CC) -E $(CFLAGS) $(INCLUDES) -c $< > $@ + +clean: + rm -rf $(OBJ) diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c new file mode 100644 index 0000000000000000000000000000000000000000..e97023c600b722162bf93d7e39cdbfe96442639b --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c @@ -0,0 +1,123 @@ +/* + * 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) 1995-2015, The R Core Team + * Copyright (c) 2003, The R Foundation + * Copyright (c) 2015, 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +#include <rffiutils.h> +#include <stdlib.h> +#include <string.h> + +#define T_MEM_TABLE_INITIAL_SIZE 0 +// The table of transient objects that have been allocated dur the current FFI call +static void **tMemTable; +// hwm of tMemTable +static int tMemTableIndex; +static int tMemTableLength; + +void init_memory() { + tMemTable = malloc(sizeof(void*) * T_MEM_TABLE_INITIAL_SIZE); + tMemTableLength = T_MEM_TABLE_INITIAL_SIZE; + tMemTableIndex = 0; +} + +void *R_chk_calloc(size_t nelem, size_t elsize); + +// Memory that is auto-reclaimed across FFI calls +char *R_alloc(size_t n, int size) { + void *p = R_chk_calloc(n, size); + if (tMemTableIndex >= tMemTableLength) { + int newLength = 2 * tMemTableLength; + void *newtMemTable = malloc(sizeof(void*) * newLength); + if (newtMemTable == NULL) { + fatalError("malloc failure"); + } + memcpy(newtMemTable, tMemTable, tMemTableLength * sizeof(void*)); + free(tMemTable); + tMemTable = newtMemTable; + tMemTableLength = newLength; + } + tMemTable[tMemTableIndex] = p; + return (char*) p; +} + +char* S_alloc(long n, int size) { + char *p = R_alloc(n, size); + memset(p, 0, n); + return p; +} + +char* S_realloc(char *p, long a, long b, int size) { + return unimplemented("S_realloc"); +} + +void allocExit() { + int i; + for (i = 0; i < tMemTableIndex; i++) { + free(tMemTable[i]); + } +} + +void *R_chk_calloc(size_t nelem, size_t elsize) { + void *p; +#ifndef HAVE_WORKING_CALLOC + if (nelem == 0) + return (NULL); +#endif + p = calloc(nelem, elsize); + if (!p) /* problem here is that we don't have a format for size_t. */ + error("'Calloc' could not allocate memory (%.0f of %u bytes)", + (double) nelem, elsize); + return (p); +} + +void *R_chk_realloc(void *ptr, size_t size) { + void *p; + /* Protect against broken realloc */ + if(ptr) p = realloc(ptr, size); else p = malloc(size); + if(!p) + error("'Realloc' could not re-allocate memory (%.0f bytes)", + (double) size); + return(p); +} + +void R_chk_free(void *ptr) { + if(ptr) { + free(ptr); + } +} + +int VMAX_MAGIC = 1234; + +void* vmaxget(void) { +// unimplemented("vmaxget"); + // ignored + return &VMAX_MAGIC; +} + +void vmaxset(const void * x) { +// unimplemented("vmaxget"); + if (x != &VMAX_MAGIC) { + unimplemented("vmaxset with different value"); + } +} + +void R_gc(void) { + unimplemented("R_gc"); +} + +int R_gc_running() { + unimplemented("R_gc_running"); + return 0; +} + +SEXP Rf_allocS4Object() { + unimplemented("Rf_allocS4Object unimplemented"); + return NULL; +} + diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c new file mode 100644 index 0000000000000000000000000000000000000000..4a0ffaaae603d76c60e22df03ca9641d731431a9 --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c @@ -0,0 +1,134 @@ +/* + * 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) 1995-2012, The R Core Team + * Copyright (c) 2003, The R Foundation + * Copyright (c) 2014, 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +#include <rffiutils.h> +#include <Rdynload.h> +#include <stdio.h> + +static void (*call_registerRoutines)(DllInfo *dllInfo, int nstOrd, int num, long routines); +static int (*call_useDynamicSymbols)(DllInfo *dllInfo, Rboolean value); +static TruffleObject (*call_setDotSymbolValues)(DllInfo *dllInfo, char *name, long fun, int numArgs); +static int (*call_forceSymbols)(DllInfo *dllInfo, Rboolean value); + +#define registerRoutines_x 0 +#define useDynamicSymbols_x 1 +#define setDotSymbolValues_x 2 +#define forceSymbols_x 3 + +void Rdynload_init(int index, void* closure) { + newClosureRef(closure); + switch (index) { + case registerRoutines_x: call_registerRoutines = closure; break; + case useDynamicSymbols_x: call_useDynamicSymbols = closure; break; + case setDotSymbolValues_x: call_setDotSymbolValues = closure; break; + case forceSymbols_x: call_forceSymbols = closure; break; + } +} + +// Must match ordinal value for DLL.NativeSymbolType +#define C_NATIVE_TYPE 0 +#define CALL_NATIVE_TYPE 1 +#define FORTRAN_NATIVE_TYPE 2 +#define EXTERNAL_NATIVE_TYPE 3 + +int +R_registerRoutines(DllInfo *info, const R_CMethodDef * const croutines, + const R_CallMethodDef * const callRoutines, + const R_FortranMethodDef * const fortranRoutines, + const R_ExternalMethodDef * const externalRoutines) { + int num; + if (croutines) { + for(num = 0; croutines[num].name != NULL; num++) {;} + //printf("R_registerRoutines %p,%d,%d,%p\n", info, C_NATIVE_TYPE, num, croutines); + call_registerRoutines(info, C_NATIVE_TYPE, num, (long) croutines); + } + if (callRoutines) { + for(num = 0; callRoutines[num].name != NULL; num++) {;} + //printf("R_registerRoutines %p,%d,%d,%p\n", info, CALL_NATIVE_TYPE, num, callRoutines); + call_registerRoutines(info, CALL_NATIVE_TYPE, num, (long) callRoutines); + } + if (fortranRoutines) { + for(num = 0; fortranRoutines[num].name != NULL; num++) {;} + //printf("R_registerRoutines %p,%p,%d,%d,%p\n", call_registerRoutines, info, FORTRAN_NATIVE_TYPE, num, fortranRoutines); + call_registerRoutines(info, FORTRAN_NATIVE_TYPE, num, (long) fortranRoutines); + } + if (externalRoutines) { + for(num = 0; externalRoutines[num].name != NULL; num++) {;} + //printf("R_registerRoutines %p,%d,%d,%p\n", info, EXTERNAL_NATIVE_TYPE, num, externalRoutines); + call_registerRoutines(info, EXTERNAL_NATIVE_TYPE, num, (long) externalRoutines); + } + return 1; +} + +Rboolean R_useDynamicSymbols(DllInfo *dllInfo, Rboolean value) { + return call_useDynamicSymbols(dllInfo, value); +} + +Rboolean R_forceSymbols(DllInfo *dllInfo, Rboolean value) { + return call_forceSymbols(dllInfo, value); +} + + + +TruffleObject Rdynload_setSymbol(DllInfo *info, int nstOrd, long routinesAddr, int index) { + const char *name; + long fun; + int numArgs; + switch (nstOrd) { + case C_NATIVE_TYPE: { + R_CMethodDef *croutines = (R_CMethodDef *) routinesAddr; + name = croutines[index].name; + fun = (long) croutines[index].fun; + numArgs = croutines[index].numArgs; + break; + } + case CALL_NATIVE_TYPE: { + R_CallMethodDef *callRoutines = (R_CallMethodDef *) routinesAddr; + name = callRoutines[index].name; + fun = (long) callRoutines[index].fun; + numArgs = callRoutines[index].numArgs; + break; + } + case FORTRAN_NATIVE_TYPE: { + R_FortranMethodDef * fortranRoutines = (R_FortranMethodDef *) routinesAddr; + name = fortranRoutines[index].name; + fun = (long) fortranRoutines[index].fun; + numArgs = fortranRoutines[index].numArgs; + break; + } + case EXTERNAL_NATIVE_TYPE: { + R_ExternalMethodDef * externalRoutines = (R_ExternalMethodDef *) routinesAddr; + name = externalRoutines[index].name; + fun = (long) externalRoutines[index].fun; + numArgs = externalRoutines[index].numArgs; + break; + } + } + //printf("call_setDotSymbolValues %p, %s, %p, %d\n", info, name, fun, numArgs); + TruffleObject result = call_setDotSymbolValues(info, (char *)name, fun, numArgs); + + return result; +} + +extern SEXP unimplemented(char *fun); + +void R_RegisterCCallable(const char *package, const char *name, DL_FUNC fptr) { + // we ignore this for now +} + +DL_FUNC R_GetCCallable(const char *package, const char *name) { + return unimplemented("R_GetCCallable"); +} + +DL_FUNC R_FindSymbol(char const *name, char const *pkg, + R_RegisteredNativeSymbol *symbol) { + return unimplemented("R_FindSymbol"); +} diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rembedded.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rembedded.c new file mode 100644 index 0000000000000000000000000000000000000000..c60dc95c6a328c87e5577dd25a7f07028612d7ca --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rembedded.c @@ -0,0 +1,29 @@ +/* + * 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 + * 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. + */ +#include <Rinterface.h> +#include <rffiutils.h> + +char *R_HomeDir(void) { + return ((call_R_HomeDir) callbacks[R_HomeDir_x])(); +} + diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Riconv.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Riconv.c new file mode 100644 index 0000000000000000000000000000000000000000..455826794f5edee7adea978787d72a1839d411d0 --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Riconv.c @@ -0,0 +1,39 @@ +/* + * 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. + */ +#include <rffiutils.h> +#include <Riconv.h> + +void * Riconv_open (const char* tocode, const char* fromcode) { + return unimplemented("Riconv_open"); +} + +size_t Riconv (void * cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) { + unimplemented("Riconv"); + return 0; +} + +int Riconv_close (void * cd) { + unimplemented("Riconv_close"); + return 0; +} diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c new file mode 100644 index 0000000000000000000000000000000000000000..b3005b14480ecd1a403b3fd1e25719a93b604fa4 --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c @@ -0,0 +1,1175 @@ +/* + * 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 + * 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. + */ +#include <Rinterface.h> +#include <rffiutils.h> +#include <rffi_callbacks.h> +#include <Rinternals_common.h> + +void *callbacks[CALLBACK_TABLE_SIZE]; + +void Rinternals_addCallback(int index, void *closure) { + newClosureRef(closure); + callbacks[index] = closure; +} + +static int* return_int; +static double* return_double; +static char* return_byte; + +long return_INTEGER_CREATE(int *value, int len) { + int* idata = malloc(len * sizeof(int)); + memcpy(idata, value, len * sizeof(int)); + return_int = idata; + return (long) idata; +} + +long return_DOUBLE_CREATE(double *value, int len) { + double* ddata = malloc(len * sizeof(double)); + memcpy(ddata, value, len * sizeof(double)); + return_double = ddata; + return (long) ddata; +} + +long return_BYTE_CREATE(char *value, int len, int isString) { + if (isString) { + len += 1; + } + char* bdata = malloc(len * sizeof(char)); + memcpy(bdata, value, len * sizeof(char)); + if (isString) { + bdata[len] = 0; + } + return_byte = bdata; + return (long) bdata; +} + +void return_INTEGER_EXISTING(long address) { + return_int = (int*) address; +} + +void return_DOUBLE_EXISTING(long address) { + return_double = (double*) address; +} + +void return_BYTE_EXISTING(long address) { + return_byte = (char*) address; +} + +void return_FREE(void *address) { +// free(address); +} + +// R_GlobalEnv et al are not a variables in FASTR as they are RContext specific +SEXP FASTR_R_GlobalEnv() { + return ((call_R_GlobalEnv) callbacks[R_GlobalEnv_x])(); +} + +SEXP FASTR_R_BaseEnv() { + return ((call_R_BaseEnv) callbacks[R_BaseEnv_x])(); +} + +SEXP FASTR_R_BaseNamespace() { + return ((call_R_BaseNamespace) callbacks[R_BaseNamespace_x])(); +} + +SEXP FASTR_R_NamespaceRegistry() { + return ((call_R_NamespaceRegistry) callbacks[R_NamespaceRegistry_x])(); +} + +CTXT FASTR_GlobalContext() { + return ((call_R_GlobalContext) callbacks[R_GlobalContext_x])(); +} + +Rboolean FASTR_R_Interactive() { + return (int) ((call_R_Interactive) callbacks[R_Interactive_x])(); +} + +SEXP CAR(SEXP e) { + return ((call_CAR) callbacks[CAR_x])(e); +} + +SEXP CDR(SEXP e) { + return ((call_CDR) callbacks[CDR_x])(e); +} + +int *INTEGER(SEXP x) { + ((call_INTEGER) callbacks[INTEGER_x])(x); + return return_int; +} + +int *LOGICAL(SEXP x){ + ((call_LOGICAL) callbacks[LOGICAL_x])(x); + return return_int; +} + +double *REAL(SEXP x){ + ((call_REAL) callbacks[REAL_x])(x); + return return_double; +} + +Rbyte *RAW(SEXP x) { + ((call_RAW) callbacks[RAW_x])(x); + return (Rbyte *) return_byte; +} + +int LENGTH(SEXP x) { + return ((call_LENGTH) callbacks[LENGTH_x])(x); +} + +const char * R_CHAR(SEXP x) { + ((call_R_CHAR) callbacks[R_CHAR_x])(x); + return return_byte; +} + +SEXP Rf_ScalarString(SEXP value) { + return ((call_Rf_ScalarString) callbacks[Rf_ScalarString_x])(value); +} + +SEXP Rf_mkChar(const char *x) { + return Rf_mkCharLenCE(x, strlen(x), CE_NATIVE); +} + +SEXP Rf_mkCharCE(const char *x, cetype_t y) { + return Rf_mkCharLenCE(x, strlen(x), y); +} + +SEXP Rf_mkCharLen(const char *x, int y) { + return Rf_mkCharLenCE(x, y, CE_NATIVE); +} + +SEXP Rf_mkCharLenCE(const char *x, int len, cetype_t enc) { + return ((call_Rf_mkCharLenCE) callbacks[Rf_mkCharLenCE_x])(x,len, enc); +} + +SEXP Rf_mkString(const char *s) { + return ScalarString(Rf_mkChar(s)); +} + +void Rf_gsetVar(SEXP symbol, SEXP value, SEXP rho) { + ((call_Rf_gsetVar) callbacks[Rf_gsetVar_x])(symbol, value, rho); +} + +SEXP Rf_coerceVector(SEXP x, SEXPTYPE mode) { + return ((call_Rf_coerceVector) callbacks[Rf_coerceVector_x])(x, mode); +} + +SEXP Rf_cons(SEXP car, SEXP cdr) { + return ((call_Rf_cons) callbacks[Rf_cons_x])(car, cdr); +} + +SEXP Rf_GetOption1(SEXP tag) { + return ((call_Rf_GetOption1) callbacks[Rf_GetOption1_x])(tag); +} + +#define BUFSIZE 8192 + +static int Rvsnprintf(char *buf, size_t size, const char *format, va_list ap) +{ + int val; + val = vsnprintf(buf, size, format, ap); + buf[size-1] = '\0'; + return val; +} + + +void Rf_error(const char *format, ...) { + // TODO fix this + // This is a bit tricky. The usual error handling model in Java is "throw RError.error(...)" but + // RError.error does quite a lot of stuff including potentially searching for R condition handlers + // and, if it finds any, does not return, but throws a different exception than RError. + // We definitely need to exit the FFI call and we certainly cannot return to our caller. + // So we call RFFIUpCallsObject.Rf_error to throw the RError exception. When the pending + // exception (whatever it is) is observed by JNI, the call to Rf_error will return where we do a + // non-local transfer of control back to the entry point (which will cleanup). + char buf[8192]; + va_list(ap); + va_start(ap,format); + Rvsnprintf(buf, BUFSIZE - 1, format, ap); + va_end(ap); + // This will set a pending exception (in JNI) + ((call_Rf_error) callbacks[Rf_error_x])(buf); + // just transfer back which will cleanup and exit the entire JNI call +// longjmp(*getErrorJmpBuf(), 1); + // Should not reach here + unimplemented("Rf_error"); +} + +void Rf_errorcall(SEXP x, const char *format, ...) { + unimplemented("Rf_errorcall"); +} + +void Rf_warningcall(SEXP x, const char *format, ...) { + char buf[8192]; + va_list(ap); + va_start(ap,format); + Rvsnprintf(buf, BUFSIZE - 1, format, ap); + va_end(ap); + ((call_Rf_warningcall) callbacks[Rf_warningcall_x])(x, buf); +} + +void Rf_warning(const char *format, ...) { + char buf[8192]; + va_list(ap); + va_start(ap, format); + Rvsnprintf(buf, BUFSIZE - 1, format, ap); + va_end(ap); + ((call_Rf_warning) callbacks[Rf_warning_x])(buf); +} + +void Rprintf(const char *format, ...) { + char buf[8192]; + va_list(ap); + va_start(ap,format); + Rvsnprintf(buf, BUFSIZE - 1, format, ap); + va_end(ap); + ((call_Rprintf) callbacks[Rprintf_x])(buf); +} + +/* + REprintf is used by the error handler do not add + anything unless you're sure it won't + cause problems +*/ +void REprintf(const char *format, ...) +{ + // TODO: determine correct target for this message + char buf[8192]; + va_list(ap); + va_start(ap,format); + Rvsnprintf(buf, BUFSIZE - 1, format, ap); + va_end(ap); + // TODO +} + +void Rvprintf(const char *format, va_list args) { + unimplemented("Rvprintf"); +} +void REvprintf(const char *format, va_list args) { + unimplemented("REvprintf"); +} + + +SEXP Rf_ScalarInteger(int value) { + return ((call_Rf_ScalarInteger) callbacks[Rf_ScalarInteger_x])(value); +} + +SEXP Rf_ScalarReal(double value) { + return ((call_Rf_ScalarReal) callbacks[Rf_ScalarDouble_x])(value); +} + +SEXP Rf_ScalarLogical(int value) { + return ((call_Rf_ScalarLogical) callbacks[Rf_ScalarLogical_x])(value); +} + +SEXP Rf_allocVector3(SEXPTYPE t, R_xlen_t len, R_allocator_t* allocator) { + if (allocator != NULL) { + unimplemented("RF_allocVector with custom allocator"); + return NULL; + } + return ((call_Rf_allocVector) callbacks[Rf_allocVector_x])(t, len); +} + +SEXP Rf_allocArray(SEXPTYPE t, SEXP dims) { + return ((call_Rf_allocArray) callbacks[Rf_allocArray_x])(t, dims); +} + +SEXP Rf_alloc3DArray(SEXPTYPE t, int x, int y, int z) { + return unimplemented("Rf_alloc3DArray"); +} + +SEXP Rf_allocMatrix(SEXPTYPE mode, int nrow, int ncol) { + return ((call_Rf_allocMatrix) callbacks[Rf_allocMatrix_x])(mode, nrow, ncol); +} + +SEXP Rf_allocList(int x) { + unimplemented("Rf_allocList)"); + return NULL; +} + +SEXP Rf_allocSExp(SEXPTYPE t) { + return unimplemented("Rf_allocSExp"); +} + +void Rf_defineVar(SEXP symbol, SEXP value, SEXP rho) { + ((call_Rf_defineVar) callbacks[Rf_defineVar_x])(symbol, value, rho); +} + +void Rf_setVar(SEXP x, SEXP y, SEXP z) { + unimplemented("Rf_setVar"); +} + +SEXP Rf_dimgets(SEXP x, SEXP y) { + return unimplemented("Rf_dimgets"); +} + +SEXP Rf_dimnamesgets(SEXP x, SEXP y) { + return unimplemented("Rf_dimnamesgets"); +} + +SEXP Rf_eval(SEXP expr, SEXP env) { + return ((call_Rf_eval) callbacks[Rf_eval_x])(expr, env); +} + +SEXP Rf_findFun(SEXP symbol, SEXP rho) { + return ((call_Rf_findFun) callbacks[Rf_findFun_x])(symbol, rho); +} + +SEXP Rf_findVar(SEXP sym, SEXP rho) { + return ((call_Rf_findVar) callbacks[Rf_findVar_x])(sym, rho); +} + +SEXP Rf_findVarInFrame(SEXP rho, SEXP sym) { + return ((call_Rf_findVarInFrame) callbacks[Rf_findVarInFrame_x])(rho, sym); +} + +SEXP Rf_findVarInFrame3(SEXP rho, SEXP sym, Rboolean b) { + return ((call_Rf_findVarInFrame3) callbacks[Rf_findVarInFrame3_x])(rho, sym, b); +} + +SEXP Rf_getAttrib(SEXP vec, SEXP name) { + SEXP result = ((call_Rf_getAttrib) callbacks[Rf_getAttrib_x])(vec, name); +// printf("Rf_getAttrib: %p\n", result); + return result; +} + +SEXP Rf_setAttrib(SEXP vec, SEXP name, SEXP val) { + return ((call_Rf_setAttrib) callbacks[Rf_setAttrib_x])(vec, name, val); +} + +SEXP Rf_duplicate(SEXP x) { + return ((call_Rf_duplicate) callbacks[Rf_duplicate_x])(x, 1); +} + +SEXP Rf_shallow_duplicate(SEXP x) { + return ((call_Rf_duplicate) callbacks[Rf_duplicate_x])(x, 0); +} + +R_xlen_t Rf_any_duplicated(SEXP x, Rboolean from_last) { + return (R_xlen_t) ((call_Rf_any_duplicated) callbacks[Rf_any_duplicated_x])(x, from_last); +} + +SEXP Rf_duplicated(SEXP x, Rboolean y) { + unimplemented("Rf_duplicated"); + return NULL; +} + +SEXP Rf_applyClosure(SEXP x, SEXP y, SEXP z, SEXP a, SEXP b) { + return unimplemented("Rf_applyClosure"); +} + +void Rf_copyMostAttrib(SEXP x, SEXP y) { + unimplemented("Rf_copyMostAttrib"); +} + +void Rf_copyVector(SEXP x, SEXP y) { + unimplemented("Rf_copyVector"); +} + +int Rf_countContexts(int x, int y) { + return (int) unimplemented("Rf_countContexts"); +} + +Rboolean Rf_inherits(SEXP x, const char * klass) { + return (Rboolean) ((call_Rf_inherits) callbacks[Rf_inherits_x])(x, klass); +} + +Rboolean Rf_isObject(SEXP s) { + unimplemented("Rf_isObject"); + return FALSE; +} + +void Rf_PrintValue(SEXP x) { + unimplemented("Rf_PrintValue"); +} + +SEXP Rf_install(const char *name) { + return ((call_Rf_install) callbacks[Rf_install_x])(name); +} + +SEXP Rf_installChar(SEXP charsxp) { + return ((call_Rf_installChar) callbacks[Rf_installChar_x])(charsxp); +} + +Rboolean Rf_isNull(SEXP s) { + return (Rboolean) ((call_Rf_isNull) callbacks[Rf_isNull_x])(s); +} + +Rboolean Rf_isString(SEXP s) { + return (Rboolean) ((call_Rf_isString) callbacks[Rf_isString_x])(s); +} + +Rboolean R_cycle_detected(SEXP s, SEXP child) { + unimplemented("R_cycle_detected"); + return 0; +} + +cetype_t Rf_getCharCE(SEXP x) { + // unimplemented("Rf_getCharCE"); + // TODO: real implementation + return CE_NATIVE; +} + +const char *Rf_reEnc(const char *x, cetype_t ce_in, cetype_t ce_out, int subst) { + // TODO proper implementation + return x; +} + +int Rf_ncols(SEXP x) { + return (int) ((call_Rf_ncols) callbacks[Rf_ncols_x])(x); +} + +int Rf_nrows(SEXP x) { + return (int) ((call_Rf_nrows) callbacks[Rf_nrows_x])(x); +} + + +SEXP Rf_protect(SEXP x) { + return x; +} + +void Rf_unprotect(int x) { +} + +void R_ProtectWithIndex(SEXP x, PROTECT_INDEX *y) { + // +} + +void R_Reprotect(SEXP x, PROTECT_INDEX y) { + // +} + + +void Rf_unprotect_ptr(SEXP x) { + // +} + + +void R_FlushConsole(void) { + // ignored +} + +void R_ProcessEvents(void) { + unimplemented("R_ProcessEvents"); +} + +// Tools package support, not in public API +SEXP R_NewHashedEnv(SEXP parent, SEXP size) { + return ((call_R_NewHashedEnv) callbacks[R_NewHashedEnv_x])(parent, size); +} + +SEXP Rf_classgets(SEXP vec, SEXP klass) { + return ((call_Rf_classgets) callbacks[Rf_classgets_x])(vec, klass); +} + +const char *Rf_translateChar(SEXP x) { + // TODO: proper implementation + const char *result = CHAR(x); + return result; +} + +const char *Rf_translateChar0(SEXP x) { + // TODO: proper implementation + const char *result = CHAR(x); + return result; +} + +const char *Rf_translateCharUTF8(SEXP x) { + // TODO: proper implementation + const char *result = CHAR(x); + return result; +} + +SEXP Rf_lengthgets(SEXP x, R_len_t y) { + return ((call_Rf_lengthgets) callbacks[Rf_lengthgets_x])(x, y); +} + +SEXP Rf_xlengthgets(SEXP x, R_xlen_t y) { + return unimplemented("Rf_xlengthgets"); +} + +SEXP R_lsInternal(SEXP env, Rboolean all) { + return R_lsInternal3(env, all, TRUE); +} + +SEXP R_lsInternal3(SEXP env, Rboolean all, Rboolean sorted) { + return ((call_R_lsInternal3) callbacks[R_lsInternal3_x])(env, all, sorted); +} + +SEXP Rf_namesgets(SEXP x, SEXP y) { + return unimplemented("Rf_namesgets"); +} + +SEXP TAG(SEXP e) { + return ((call_TAG) callbacks[TAG_x])(e); +} + +SEXP PRINTNAME(SEXP e) { + return ((call_PRINTNAME) callbacks[PRINTNAME_x])(e); +} + + +SEXP CAAR(SEXP e) { + unimplemented("CAAR"); + return NULL; +} + +SEXP CDAR(SEXP e) { + unimplemented("CDAR"); + return NULL; +} + +SEXP CADR(SEXP e) { + return ((call_CADR) callbacks[CADR_x])(e); +} + +SEXP CDDR(SEXP e) { + return ((call_CDDR) callbacks[CDDR_x])(e); +} + +SEXP CDDDR(SEXP e) { + unimplemented("CDDDR"); + return NULL; +} + +SEXP CADDR(SEXP e) { + return ((call_CADDR) callbacks[CADDR_x])(e); +} + +SEXP CADDDR(SEXP e) { + unimplemented("CADDDR"); + return NULL; +} + +SEXP CAD4R(SEXP e) { + unimplemented("CAD4R"); + return NULL; +} + +int MISSING(SEXP x){ + unimplemented("MISSING"); + return 0; +} + +void SET_MISSING(SEXP x, int v) { + unimplemented("SET_MISSING"); +} + +void SET_TAG(SEXP x, SEXP y) { + ((call_SET_TAG) callbacks[SET_TAG_x])(x, y); +} + +SEXP SETCAR(SEXP x, SEXP y) { + return ((call_SETCAR) callbacks[SETCAR_x])(x, y); +} + +SEXP SETCDR(SEXP x, SEXP y) { + return ((call_SETCDR) callbacks[SETCDR_x])(x, y); +} + +SEXP SETCADR(SEXP x, SEXP y) { + return ((call_SETCADR) callbacks[SETCADR_x])(x, y); +} + +SEXP SETCADDR(SEXP x, SEXP y) { + unimplemented("SETCADDR"); + return NULL; +} + +SEXP SETCADDDR(SEXP x, SEXP y) { + unimplemented("SETCADDDR"); + return NULL; +} + +SEXP SETCAD4R(SEXP e, SEXP y) { + unimplemented("SETCAD4R"); + return NULL; +} + +SEXP FORMALS(SEXP x) { + return unimplemented("FORMALS"); +} + +SEXP BODY(SEXP x) { + return unimplemented("BODY"); +} + +SEXP CLOENV(SEXP x) { + return unimplemented("CLOENV"); +} + +int RDEBUG(SEXP x) { + return ((call_RDEBUG) callbacks[RDEBUG_x])(x); +} + +int RSTEP(SEXP x) { + return ((call_RSTEP) callbacks[RSTEP_x])(x); +} + +int RTRACE(SEXP x) { + unimplemented("RTRACE"); + return 0; +} + +void SET_RDEBUG(SEXP x, int v) { + ((call_SET_RDEBUG) callbacks[SET_RDEBUG_x])(x, v); +} + +void SET_RSTEP(SEXP x, int v) { + ((call_SET_RSTEP) callbacks[SET_RSTEP_x])(x, v); +} + +void SET_RTRACE(SEXP x, int v) { + unimplemented("SET_RTRACE"); +} + +void SET_FORMALS(SEXP x, SEXP v) { + unimplemented("SET_FORMALS"); +} + +void SET_BODY(SEXP x, SEXP v) { + unimplemented("SET_BODY"); +} + +void SET_CLOENV(SEXP x, SEXP v) { + unimplemented("SET_CLOENV"); +} + +SEXP SYMVALUE(SEXP x) { + return ((call_SYMVALUE) callbacks[SYMVALUE_x])(x); +} + +SEXP INTERNAL(SEXP x) { + return unimplemented("INTERNAL"); +} + +int DDVAL(SEXP x) { + unimplemented("DDVAL"); + return 0; +} + +void SET_DDVAL(SEXP x, int v) { + unimplemented("SET_DDVAL"); +} + +void SET_SYMVALUE(SEXP x, SEXP v) { + ((call_SET_SYMVALUE) callbacks[SET_SYMVALUE_x])(x, v); +} + +void SET_INTERNAL(SEXP x, SEXP v) { + unimplemented("SET_INTERNAL"); +} + +SEXP FRAME(SEXP x) { + return unimplemented("FRAME"); +} + +SEXP ENCLOS(SEXP x) { + return ((call_ENCLOS) callbacks[ENCLOS_x])(x); +} + +SEXP HASHTAB(SEXP x) { + return unimplemented("HASHTAB"); +} + +int ENVFLAGS(SEXP x) { + unimplemented("ENVFLAGS"); + return 0; +} + +void SET_ENVFLAGS(SEXP x, int v) { + unimplemented("SET_ENVFLAGS"); +} + +void SET_FRAME(SEXP x, SEXP v) { + unimplemented("SET_FRAME"); +} + +void SET_ENCLOS(SEXP x, SEXP v) { + unimplemented("SET_ENCLOS"); +} + +void SET_HASHTAB(SEXP x, SEXP v) { + unimplemented("SET_HASHTAB"); +} + +SEXP PRCODE(SEXP x) { + return ((call_PRCODE) callbacks[PRCODE_x])(x); +} + +SEXP PRENV(SEXP x) { + return ((call_PRENV) callbacks[PRENV_x])(x); +} + +SEXP PRVALUE(SEXP x) { + return ((call_PRVALUE) callbacks[PRVALUE_x])(x); +} + +int PRSEEN(SEXP x) { + return ((call_PRSEEN) callbacks[PRSEEN_x])(x); +} + +void SET_PRSEEN(SEXP x, int v) { + unimplemented("SET_PRSEEN"); +} + +void SET_PRENV(SEXP x, SEXP v) { + unimplemented("SET_PRENV"); +} + +void SET_PRVALUE(SEXP x, SEXP v) { + unimplemented("SET_PRVALUE"); +} + +void SET_PRCODE(SEXP x, SEXP v) { + unimplemented("SET_PRCODE"); +} + +int TRUELENGTH(SEXP x){ + unimplemented("unimplemented"); + return 0; +} + + +void SETLENGTH(SEXP x, int v){ + unimplemented("SETLENGTH"); +} + + +void SET_TRUELENGTH(SEXP x, int v){ + unimplemented("SET_TRUELENGTH"); +} + + +R_xlen_t XLENGTH(SEXP x){ + // xlength seems to be used for long vectors (no such thing in FastR at the moment) + return LENGTH(x); +} + + +R_xlen_t XTRUELENGTH(SEXP x){ + unimplemented("XTRUELENGTH"); + return 0; +} + + +int IS_LONG_VEC(SEXP x){ + unimplemented("IS_LONG_VEC"); + return 0; +} + + +int LEVELS(SEXP x){ + unimplemented("LEVELS"); + return 0; +} + + +int SETLEVELS(SEXP x, int v){ + unimplemented("SETLEVELS"); + return 0; +} + +Rcomplex *COMPLEX(SEXP x){ + unimplemented("COMPLEX"); + return NULL; +} + +SEXP STRING_ELT(SEXP x, R_xlen_t i) { + return ((call_STRING_ELT) callbacks[STRING_ELT_x])(x, i); +} + + +SEXP VECTOR_ELT(SEXP x, R_xlen_t i){ + return ((call_VECTOR_ELT) callbacks[VECTOR_ELT_x])(x, i); +} + +void SET_STRING_ELT(SEXP x, R_xlen_t i, SEXP v){ + ((call_SET_STRING_ELT) callbacks[SET_STRING_ELT_x])(x, i, v); +} + + +SEXP SET_VECTOR_ELT(SEXP x, R_xlen_t i, SEXP v){ + return ((call_SET_VECTOR_ELT) callbacks[SET_VECTOR_ELT_x])(x, i, v); +} + +SEXP *STRING_PTR(SEXP x){ + unimplemented("STRING_PTR"); + return NULL; +} + + +SEXP * NORET VECTOR_PTR(SEXP x){ + unimplemented("VECTOR_PTR"); +} + +SEXP Rf_asChar(SEXP x){ + return ((call_Rf_asChar) callbacks[Rf_asChar_x])(x); +} + +SEXP Rf_PairToVectorList(SEXP x){ + return ((call_Rf_PairToVectorList) callbacks[Rf_PairToVectorList_x])(x); +} + +SEXP Rf_VectorToPairList(SEXP x){ + return unimplemented("Rf_VectorToPairList"); +} + +SEXP Rf_asCharacterFactor(SEXP x){ + unimplemented("Rf_VectorToPairList"); + return NULL; +} + +int Rf_asLogical(SEXP x){ + return ((call_Rf_asLogical) callbacks[Rf_asLogical_x])(x); +} + +int Rf_asInteger(SEXP x) { + return ((call_Rf_asInteger) callbacks[Rf_asInteger_x])(x); +} + +double Rf_asReal(SEXP x) { + return ((call_Rf_asReal) callbacks[Rf_asReal_x])(x); +} + +Rcomplex Rf_asComplex(SEXP x){ + unimplemented("Rf_asLogical"); + Rcomplex c; return c; +} + +int TYPEOF(SEXP x) { + return (int) ((call_TYPEOF) callbacks[TYPEOF_x])(x); +} + +SEXP ATTRIB(SEXP x){ + unimplemented("ATTRIB"); + return NULL; +} + +int OBJECT(SEXP x){ + return (int) ((call_OBJECT) callbacks[OBJECT_x])(x); +} + +int MARK(SEXP x){ + unimplemented("MARK"); + return 0; +} + +int NAMED(SEXP x){ + return (int) ((call_NAMED) callbacks[NAMED_x])(x); +} + +int REFCNT(SEXP x){ + unimplemented("REFCNT"); + return 0; +} + +void SET_OBJECT(SEXP x, int v){ + unimplemented("SET_OBJECT"); +} + +void SET_TYPEOF(SEXP x, int v){ + unimplemented("SET_TYPEOF"); +} + +SEXP SET_TYPEOF_FASTR(SEXP x, int v){ + return ((call_SET_TYPEOF_FASTR) callbacks[SET_TYPEOF_FASTR_x])(x, v); +} + +void SET_NAMED(SEXP x, int v){ + unimplemented("SET_NAMED"); +} + +void SET_ATTRIB(SEXP x, SEXP v){ + unimplemented("SET_ATTRIB"); +} + +void DUPLICATE_ATTRIB(SEXP to, SEXP from){ + ((call_DUPLICATE_ATTRIB) callbacks[DUPLICATE_ATTRIB_x])(to, from); +} + +void R_qsort_I (double *v, int *II, int i, int j) { + unimplemented("R_qsort_I"); +} + +void R_qsort_int_I(int *iv, int *II, int i, int j) { + unimplemented("R_qsort_int_I"); +} + +R_len_t R_BadLongVector(SEXP x, const char *y, int z) { + return (R_len_t) unimplemented("R_BadLongVector"); +} + +int IS_S4_OBJECT(SEXP x) { + return (int) ((call_IS_S4_OBJECT) callbacks[IS_S4_OBJECT_x])(x); +} + +void SET_S4_OBJECT(SEXP x) { + ((call_SET_S4_OBJECT) callbacks[SET_S4_OBJECT_x])(x); +} + +void UNSET_S4_OBJECT(SEXP x) { + ((call_UNSET_S4_OBJECT) callbacks[UNSET_S4_OBJECT_x])(x); +} + +Rboolean R_ToplevelExec(void (*fun)(void *), void *data) { + return (Rboolean) unimplemented("R_ToplevelExec"); +} + +SEXP R_ExecWithCleanup(SEXP (*fun)(void *), void *data, + void (*cleanfun)(void *), void *cleandata) { + return unimplemented("R_ExecWithCleanup"); +} + +/* Environment and Binding Features */ +void R_RestoreHashCount(SEXP rho) { + unimplemented("R_RestoreHashCount"); +} + +Rboolean R_IsPackageEnv(SEXP rho) { + unimplemented("R_IsPackageEnv"); +} + +SEXP R_PackageEnvName(SEXP rho) { + return unimplemented("R_PackageEnvName"); +} + +SEXP R_FindPackageEnv(SEXP info) { + return unimplemented("R_FindPackageEnv"); +} + +Rboolean R_IsNamespaceEnv(SEXP rho) { + return (Rboolean) unimplemented("R_IsNamespaceEnv"); +} + +SEXP R_FindNamespace(SEXP info) { + return ((call_R_FindNamespace) callbacks[R_FindNamespace_x])(info); +} + +SEXP R_NamespaceEnvSpec(SEXP rho) { + return unimplemented("R_NamespaceEnvSpec"); +} + +void R_LockEnvironment(SEXP env, Rboolean bindings) { + unimplemented("R_LockEnvironment"); +} + +Rboolean R_EnvironmentIsLocked(SEXP env) { + unimplemented(""); +} + +void R_LockBinding(SEXP sym, SEXP env) { + unimplemented("R_LockBinding"); +} + +void R_unLockBinding(SEXP sym, SEXP env) { + unimplemented("R_unLockBinding"); +} + +void R_MakeActiveBinding(SEXP sym, SEXP fun, SEXP env) { + unimplemented("R_MakeActiveBinding"); +} + +Rboolean R_BindingIsLocked(SEXP sym, SEXP env) { + return (Rboolean) ((call_R_BindingIsLocked) callbacks[R_BindingIsLocked_x])(sym, env); +} + +Rboolean R_BindingIsActive(SEXP sym, SEXP env) { + // TODO: for now, I believe all bindings are false + return (Rboolean)0; +} + +Rboolean R_HasFancyBindings(SEXP rho) { + return (Rboolean) unimplemented("R_HasFancyBindings"); +} + +Rboolean Rf_isS4(SEXP x) { + return IS_S4_OBJECT(x); +} + +SEXP Rf_asS4(SEXP x, Rboolean b, int i) { + unimplemented("Rf_asS4"); +} + +static SEXP R_tryEvalInternal(SEXP x, SEXP y, int *ErrorOccurred, int silent) { + unimplemented("R_tryEvalInternal"); +} + +SEXP R_tryEval(SEXP x, SEXP y, int *ErrorOccurred) { + return R_tryEvalInternal(x, y, ErrorOccurred, 0); +} + +SEXP R_tryEvalSilent(SEXP x, SEXP y, int *ErrorOccurred) { + return R_tryEvalInternal(x, y, ErrorOccurred, 1); +} + +double R_atof(const char *str) { + unimplemented("R_atof"); + return 0; +} + +double R_strtod(const char *c, char **end) { + unimplemented("R_strtod"); + return 0; +} + +SEXP R_PromiseExpr(SEXP x) { + return ((call_R_PromiseExpr) callbacks[R_PromiseExpr_x])(x); +} + +SEXP R_ClosureExpr(SEXP x) { + return unimplemented("R_ClosureExpr"); +} + +SEXP R_forceAndCall(SEXP e, int n, SEXP rho) { + return unimplemented("R_forceAndCall"); +} + +SEXP R_MakeExternalPtr(void *p, SEXP tag, SEXP prot) { + return ((call_R_MakeExternalPtr) callbacks[R_MakeExternalPtr_x])(p, tag, prot); +} + +void *R_ExternalPtrAddr(SEXP s) { + return ((call_R_ExternalPtrAddr) callbacks[R_ExternalPtrAddr_x])(s); +} + +SEXP R_ExternalPtrTag(SEXP s) { + return ((call_R_ExternalPtrTag) callbacks[R_ExternalPtrTag_x])(s); +} + +SEXP R_ExternalPtrProtected(SEXP s) { + return ((call_R_ExternalPtrProtected) callbacks[R_ExternalPtrProtected_x])(s); +} + +void R_SetExternalPtrAddr(SEXP s, void *p) { + ((call_R_SetExternalPtrProtected) callbacks[R_SetExternalPtrProtected_x])(s, p); +} + +void R_SetExternalPtrTag(SEXP s, SEXP tag) { + ((call_R_SetExternalPtrProtected) callbacks[R_SetExternalPtrProtected_x])(s, tag); +} + +void R_SetExternalPtrProtected(SEXP s, SEXP p) { + ((call_R_SetExternalPtrProtected) callbacks[R_SetExternalPtrProtected_x])(s, p); +} + +void R_ClearExternalPtr(SEXP s) { + R_SetExternalPtrAddr(s, NULL); +} + +void R_RegisterFinalizer(SEXP s, SEXP fun) { + // TODO implement, but not fail for now +} +void R_RegisterCFinalizer(SEXP s, R_CFinalizer_t fun) { + // TODO implement, but not fail for now +} + +void R_RegisterFinalizerEx(SEXP s, SEXP fun, Rboolean onexit) { + // TODO implement, but not fail for now + +} + +void R_RegisterCFinalizerEx(SEXP s, R_CFinalizer_t fun, Rboolean onexit) { + // TODO implement, but not fail for now +} + +void R_RunPendingFinalizers(void) { + // TODO implement, but not fail for now +} + +SEXP R_MakeWeakRef(SEXP key, SEXP val, SEXP fin, Rboolean onexit) { + unimplemented("R_MakeWeakRef"); +} + +SEXP R_MakeWeakRefC(SEXP key, SEXP val, R_CFinalizer_t fin, Rboolean onexit) { + unimplemented("R_MakeWeakRefC"); +} + +SEXP R_WeakRefKey(SEXP w) { + unimplemented("R_WeakRefKey"); +} + +SEXP R_WeakRefValue(SEXP w) { + unimplemented("R_WeakRefValue"); +} + +void R_RunWeakRefFinalizer(SEXP w) { + // TODO implement, but not fail for now +} + +SEXP R_do_slot(SEXP obj, SEXP name) { + return ((call_R_do_slot) callbacks[R_do_slot_x])(obj, name); +} + +SEXP R_do_slot_assign(SEXP obj, SEXP name, SEXP value) { + return ((call_R_do_slot_assign) callbacks[R_do_slot_assign_x])(obj, name, value); +} + +int R_has_slot(SEXP obj, SEXP name) { + return (int) unimplemented("R_has_slot"); +} + +SEXP R_do_MAKE_CLASS(const char *what) { + return ((call_R_do_MAKE_CLASS) callbacks[R_do_MAKE_CLASS_x])(what); +} + +SEXP R_getClassDef (const char *what) { + return unimplemented("R_getClassDef"); +} + +SEXP R_do_new_object(SEXP class_def) { + return ((call_R_do_new_object) callbacks[R_do_new_object_x])(class_def); +} + +static SEXP nfiGetMethodsNamespace() { + return ((call_R_MethodsNamespace) callbacks[R_MethodsNamespace_x])(); +} + +int R_check_class_etc (SEXP x, const char **valid) { + return R_check_class_etc_helper(x, valid, nfiGetMethodsNamespace); +} + +SEXP R_PreserveObject(SEXP x) { + return newObjectRef(x); +} + +void R_ReleaseObject(SEXP x) { + releaseObjectRef(x); +} + +void R_dot_Last(void) { + unimplemented("R_dot_Last"); +} + + +Rboolean R_compute_identical(SEXP x, SEXP y, int flags) { + return (Rboolean) ((call_R_compute_identical) callbacks[R_compute_identical_x])(x, y, flags); +} + +void Rf_copyListMatrix(SEXP s, SEXP t, Rboolean byrow) { + ((call_Rf_copyListMatrix) callbacks[Rf_copyListMatrix_x])(s, t, byrow); +} + +void Rf_copyMatrix(SEXP s, SEXP t, Rboolean byrow) { + ((call_Rf_copyMatrix) callbacks[Rf_copyMatrix_x])(s, t, byrow); +} + diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rmath.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rmath.c new file mode 100644 index 0000000000000000000000000000000000000000..f9ea65f0db4bdb5c3578d1bf2bc3b5854c719a7c --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rmath.c @@ -0,0 +1,704 @@ +/* + * 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. + */ +#include <rffiutils.h> + +double Rf_dnorm(double a, double b, double c, int d) { + unimplemented("Rf_dnorm"); + return 0; +} + +double Rf_dnorm4(double a, double b, double c, int d) { + return Rf_dnorm(a, b, c, d); +} + +double Rf_pnorm(double a, double b, double c, int d, int e) { + unimplemented("Rf_pnorm"); + return 0; +} + +double Rf_pnorm5(double a, double b, double c, int d, int e) { + return Rf_pnorm(a, b, c, d, e); +} + +double Rf_qnorm(double a, double b, double c, int d, int e) { + unimplemented("Rf_qnorm"); + return 0; +} + +double Rf_qnorm5(double a, double b, double c, int d, int e) { + return Rf_qnorm(a, b, c, d, e); +} + +double Rf_rnorm(double a, double b) { + unimplemented("Rf_rnorm"); + return 0; +} + +void Rf_pnorm_both(double a, double * b, double * c, int d, int e) { + unimplemented("Rf_pnorm_both"); +} + +double Rf_dunif(double a, double b, double c, int d) { + unimplemented("Rf_dunif"); + return 0; +} + +double Rf_punif(double a, double b, double c, int d, int e) { + unimplemented("Rf_punif"); + return 0; +} + +double Rf_qunif(double a, double b, double c, int d, int e) { + unimplemented("Rf_qunif"); + return 0; +} + +double Rf_runif(double a, double b) { + unimplemented("Rf_runif"); + return 0; +} + +double Rf_dgamma(double a, double b, double c, int d) { + unimplemented("Rf_dgamma"); + return 0; +} + +double Rf_pgamma(double a, double b, double c, int d, int e) { + unimplemented("Rf_pgamma"); + return 0; +} + +double Rf_qgamma(double a, double b, double c, int d, int e) { + unimplemented("Rf_qgamma"); + return 0; +} + +double Rf_rgamma(double a, double b) { + unimplemented("Rf_rgamma"); + return 0; +} + +double Rf_log1pmx(double a) { + unimplemented("Rf_log1pmx"); + return 0; +} + +double Rf_log1pexp(double a) { + unimplemented("Rf_log1pexp"); + return 0; +} + +double Rf_lgamma1p(double a) { + unimplemented("Rf_lgamma1p"); + return 0; +} + +double Rf_logspace_add(double a, double b) { + unimplemented("Rf_logspace_add"); + return 0; +} + +double Rf_logspace_sub(double a, double b) { + unimplemented("Rf_logspace_sub"); + return 0; +} + +double Rf_dbeta(double a, double b, double c, int d) { + unimplemented("Rf_dbeta"); + return 0; +} + +double Rf_pbeta(double a, double b, double c, int d, int e) { + unimplemented("Rf_pbeta"); + return 0; +} + +double Rf_qbeta(double a, double b, double c, int d, int e) { + unimplemented("Rf_qbeta"); + return 0; +} + +double Rf_rbeta(double a, double b) { + unimplemented("Rf_rbeta"); + return 0; +} + +double Rf_dlnorm(double a, double b, double c, int d) { + unimplemented("Rf_dlnorm"); + return 0; +} + +double Rf_plnorm(double a, double b, double c, int d, int e) { + unimplemented("Rf_plnorm"); + return 0; +} + +double Rf_qlnorm(double a, double b, double c, int d, int e) { + unimplemented("Rf_qlnorm"); + return 0; +} + +double Rf_rlnorm(double a, double b) { + unimplemented("Rf_rlnorm"); + return 0; +} + +double Rf_dchisq(double a, double b, int c) { + unimplemented("Rf_dchisq"); + return 0; +} + +double Rf_pchisq(double a, double b, int c, int d) { + unimplemented("Rf_pchisq"); + return 0; +} + +double Rf_qchisq(double a, double b, int c, int d) { + unimplemented("Rf_qchisq"); + return 0; +} + +double Rf_rchisq(double a) { + unimplemented("Rf_rchisq"); + return 0; +} + +double Rf_dnchisq(double a, double b, double c, int d) { + unimplemented("Rf_dnchisq"); + return 0; +} + +double Rf_pnchisq(double a, double b, double c, int d, int e) { + unimplemented("Rf_pnchisq"); + return 0; +} + +double Rf_qnchisq(double a, double b, double c, int d, int e) { + unimplemented("Rf_qnchisq"); + return 0; +} + +double Rf_rnchisq(double a, double b) { + unimplemented("Rf_rnchisq"); + return 0; +} + +double Rf_df(double a, double b, double c, int d) { + unimplemented("Rf_df"); + return 0; +} + +double Rf_pf(double a, double b, double c, int d, int e) { + unimplemented("Rf_pf"); + return 0; +} + +double Rf_qf(double a, double b, double c, int d, int e) { + unimplemented("Rf_qf"); + return 0; +} + +double Rf_rf(double a, double b) { + unimplemented("Rf_rf"); + return 0; +} + +double Rf_dt(double a, double b, int c) { + unimplemented("Rf_dt"); + return 0; +} + +double Rf_pt(double a, double b, int c, int d) { + unimplemented("Rf_pt"); + return 0; +} + +double Rf_qt(double a, double b, int c, int d) { + unimplemented("Rf_qt"); + return 0; +} + +double Rf_rt(double a) { + unimplemented("Rf_rt"); + return 0; +} + +double Rf_dbinom(double a, double b, double c, int d) { + unimplemented("Rf_dbinom"); + return 0; +} + +double Rf_pbinom(double a, double b, double c, int d, int e) { + unimplemented("Rf_pbinom"); + return 0; +} + +double Rf_qbinom(double a, double b, double c, int d, int e) { + unimplemented("Rf_qbinom"); + return 0; +} + +double Rf_rbinom(double a, double b) { + unimplemented("Rf_rbinom"); + return 0; +} + +void Rf_rmultinom(int a, double* b, int c, int* d) { + unimplemented("Rf_rmultinom"); +} + +double Rf_dcauchy(double a, double b, double c, int d) { + unimplemented("Rf_dcauchy"); + return 0; +} + +double Rf_pcauchy(double a, double b, double c, int d, int e) { + unimplemented("Rf_pcauchy"); + return 0; +} + +double Rf_qcauchy(double a, double b, double c, int d, int e) { + unimplemented("Rf_qcauchy"); + return 0; +} + +double Rf_rcauchy(double a, double b) { + unimplemented("Rf_rcauchy"); + return 0; +} + +double Rf_dexp(double a, double b, int c) { + unimplemented("Rf_dexp"); + return 0; +} + +double Rf_pexp(double a, double b, int c, int d) { + unimplemented("Rf_pexp"); + return 0; +} + +double Rf_qexp(double a, double b, int c, int d) { + unimplemented("Rf_qexp"); + return 0; +} + +double Rf_rexp(double a) { + unimplemented("Rf_rexp"); + return 0; +} + +double Rf_dgeom(double a, double b, int c) { + unimplemented("Rf_dgeom"); + return 0; +} + +double Rf_pgeom(double a, double b, int c, int d) { + unimplemented("Rf_pgeom"); + return 0; +} + +double Rf_qgeom(double a, double b, int c, int d) { + unimplemented("Rf_qgeom"); + return 0; +} + +double Rf_rgeom(double a) { + unimplemented("Rf_rgeom"); + return 0; +} + +double Rf_dhyper(double a, double b, double c, double d, int e) { + unimplemented("Rf_dhyper"); + return 0; +} + +double Rf_phyper(double a, double b, double c, double d, int e, int f) { + unimplemented("Rf_phyper"); + return 0; +} + +double Rf_qhyper(double a, double b, double c, double d, int e, int f) { + unimplemented("Rf_qhyper"); + return 0; +} + +double Rf_rhyper(double a, double b, double c) { + unimplemented("Rf_rhyper"); + return 0; +} + +double Rf_dnbinom(double a, double b, double c, int d) { + unimplemented("Rf_dnbinom"); + return 0; +} + +double Rf_pnbinom(double a, double b, double c, int d, int e) { + unimplemented("Rf_pnbinom"); + return 0; +} + +double Rf_qnbinom(double a, double b, double c, int d, int e) { + unimplemented("Rf_qnbinom"); + return 0; +} + +double Rf_rnbinom(double a, double b) { + unimplemented("Rf_rnbinom"); + return 0; +} + +double Rf_dnbinom_mu(double a, double b, double c, int d) { + unimplemented("Rf_dnbinom_mu"); + return 0; +} + +double Rf_pnbinom_mu(double a, double b, double c, int d, int e) { + unimplemented("Rf_pnbinom_mu"); + return 0; +} + +double Rf_qnbinom_mu(double a, double b, double c, int d, int e) { + unimplemented("Rf_qnbinom_mu"); + return 0; +} + +double Rf_rnbinom_mu(double a, double b) { + unimplemented("Rf_rnbinom_mu"); + return 0; +} + +double Rf_dpois(double a, double b, int c) { + unimplemented("Rf_dpois"); + return 0; +} + +double Rf_ppois(double a, double b, int c, int d) { + unimplemented("Rf_ppois"); + return 0; +} + +double Rf_qpois(double a, double b, int c, int d) { + unimplemented("Rf_qpois"); + return 0; +} + +double Rf_rpois(double a) { + unimplemented("Rf_rpois"); + return 0; +} + +double Rf_dweibull(double a, double b, double c, int d) { + unimplemented("Rf_dweibull"); + return 0; +} + +double Rf_pweibull(double a, double b, double c, int d, int e) { + unimplemented("Rf_pweibull"); + return 0; +} + +double Rf_qweibull(double a, double b, double c, int d, int e) { + unimplemented("Rf_qweibull"); + return 0; +} + +double Rf_rweibull(double a, double b) { + unimplemented("Rf_rweibull"); + return 0; +} + +double Rf_dlogis(double a, double b, double c, int d) { + unimplemented("Rf_dlogis"); + return 0; +} + +double Rf_plogis(double a, double b, double c, int d, int e) { + unimplemented("Rf_plogis"); + return 0; +} + +double Rf_qlogis(double a, double b, double c, int d, int e) { + unimplemented("Rf_qlogis"); + return 0; +} + +double Rf_rlogis(double a, double b) { + unimplemented("Rf_rlogis"); + return 0; +} + +double Rf_dnbeta(double a, double b, double c, double d, int e) { + unimplemented("Rf_dnbeta"); + return 0; +} + +double Rf_pnbeta(double a, double b, double c, double d, int e, int f) { + unimplemented("Rf_pnbeta"); + return 0; +} + +double Rf_qnbeta(double a, double b, double c, double d, int e, int f) { + unimplemented("Rf_qnbeta"); + return 0; +} + +double Rf_rnbeta(double a, double b, double c) { + unimplemented("Rf_rnbeta"); + return 0; +} + +double Rf_dnf(double a, double b, double c, double d, int e) { + unimplemented("Rf_dnf"); + return 0; +} + +double Rf_pnf(double a, double b, double c, double d, int e, int f) { + unimplemented("Rf_pnf"); + return 0; +} + +double Rf_qnf(double a, double b, double c, double d, int e, int f) { + unimplemented("Rf_qnf"); + return 0; +} + +double Rf_dnt(double a, double b, double c, int d) { + unimplemented("Rf_dnt"); + return 0; +} + +double Rf_pnt(double a, double b, double c, int d, int e) { + unimplemented("Rf_pnt"); + return 0; +} + +double Rf_qnt(double a, double b, double c, int d, int e) { + unimplemented("Rf_qnt"); + return 0; +} + +double Rf_ptukey(double a, double b, double c, double d, int e, int f) { + unimplemented("Rf_ptukey"); + return 0; +} + +double Rf_qtukey(double a, double b, double c, double d, int e, int f) { + unimplemented("Rf_qtukey"); + return 0; +} + +double Rf_dwilcox(double a, double b, double c, int d) { + unimplemented("Rf_dwilcox"); + return 0; +} + +double Rf_pwilcox(double a, double b, double c, int d, int e) { + unimplemented("Rf_pwilcox"); + return 0; +} + +double Rf_qwilcox(double a, double b, double c, int d, int e) { + unimplemented("Rf_qwilcox"); + return 0; +} + +double Rf_rwilcox(double a, double b) { + unimplemented("Rf_rwilcox"); + return 0; +} + +double Rf_dsignrank(double a, double b, int c) { + unimplemented("Rf_dsignrank"); + return 0; +} + +double Rf_psignrank(double a, double b, int c, int d) { + unimplemented("Rf_psignrank"); + return 0; +} + +double Rf_qsignrank(double a, double b, int c, int d) { + unimplemented("Rf_qsignrank"); + return 0; +} + +double Rf_rsignrank(double a) { + unimplemented("Rf_rsignrank"); + return 0; +} + +double Rf_gammafn(double a) { + unimplemented("Rf_gammafn"); + return 0; +} + +double Rf_lgammafn(double a) { + unimplemented("Rf_lgammafn"); + return 0; +} + +double Rf_lgammafn_sign(double a, int* b) { + unimplemented("Rf_lgammafn_sign"); + return 0; +} + +void Rf_dpsifn(double a, int b, int c, int d, double* e, int* f, int* g) { + unimplemented("Rf_dpsifn"); +} + +double Rf_psigamma(double a, double b) { + unimplemented("Rf_psigamma"); + return 0; +} + +double Rf_digamma(double a) { + unimplemented("Rf_digamma"); + return 0; +} + +double Rf_trigamma(double a) { + unimplemented("Rf_trigamma"); + return 0; +} + +double Rf_tetragamma(double a) { + unimplemented("Rf_tetragamma"); + return 0; +} + +double Rf_pentagamma(double a) { + unimplemented("Rf_pentagamma"); + return 0; +} + +double Rf_beta(double a, double b) { + unimplemented("Rf_beta"); + return 0; +} + +double Rf_lbeta(double a, double b) { + unimplemented("Rf_lbeta"); + return 0; +} + +double Rf_choose(double a, double b) { + unimplemented("Rf_choose"); + return 0; +} + +double Rf_lchoose(double a, double b) { + unimplemented("Rf_lchoose"); + return 0; +} + +double Rf_bessel_i(double a, double b, double c) { + unimplemented("Rf_bessel_i"); + return 0; +} + +double Rf_bessel_j(double a, double b) { + unimplemented("Rf_bessel_j"); + return 0; +} + +double Rf_bessel_k(double a, double b, double c) { + unimplemented("Rf_bessel_k"); + return 0; +} + +double Rf_bessel_y(double a, double b) { + unimplemented("Rf_bessel_y"); + return 0; +} + +double Rf_bessel_i_ex(double a, double b, double c, double * d) { + unimplemented("Rf_bessel_i_ex"); + return 0; +} + +double Rf_bessel_j_ex(double a, double b, double * c) { + unimplemented("Rf_bessel_j_ex"); + return 0; +} + +double Rf_bessel_k_ex(double a, double b, double c, double * d) { + unimplemented("Rf_bessel_k_ex"); + return 0; +} + +double Rf_bessel_y_ex(double a, double b, double * c) { + unimplemented("Rf_bessel_y_ex"); + return 0; +} + +int Rf_imax2(int x, int y) { + return x > y ? x : y; +} + +int Rf_imin2(int x, int y) { + return x > y ? y : x; +} + +double Rf_fmax2(double x, double y) { + return x > y ? x : y; +} + +double Rf_fmin2(double x, double y) { + return x > y ? y : x; +} + +double Rf_sign(double a) { + unimplemented("Rf_sign"); + return 0; +} + +double Rf_fprec(double a, double b) { + unimplemented("Rf_fprec"); + return 0; +} + +double Rf_fsign(double a, double b) { + unimplemented("Rf_fsign"); + return 0; +} + +double Rf_ftrunc(double a) { + unimplemented("Rf_ftrunc"); + return 0; +} + +double Rf_cospi(double a) { + unimplemented("Rf_cospi"); + return 0; +} + +double Rf_sinpi(double a) { + unimplemented("Rf_sinpi"); + return 0; +} + +double Rf_tanpi(double a) { + unimplemented("Rf_tanpi"); + return 0; +} + diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryNode.java b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Utils.c similarity index 70% rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryNode.java rename to com.oracle.truffle.r.native/fficall/src/truffle_nfi/Utils.c index 36f9c1ca7505be6d75c2ac06bde56adb190c2d46..0c491038318775d0c723d6e87553fd5b8fe97b91 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryNode.java +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Utils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, 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 @@ -20,17 +20,25 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.nodes.binary; -import com.oracle.truffle.api.dsl.NodeChild; -import com.oracle.truffle.r.runtime.nodes.RNode; +#include <rffiutils.h> -@NodeChild(value = "left", type = RNode.class) -@NodeChild(value = "right", type = RNode.class) -abstract class BinaryNode extends RNode { +void R_CheckStack(void) { + // TODO: check for stack overflow + // ignored +} - protected abstract RNode getLeft(); +void R_CheckStack2(size_t extra) { + // TODO: check for stack overflow + // ignored +} - protected abstract RNode getRight(); +void R_CheckUserInterrupt(void) { + // ignored +} +void Rf_onintr() +{ + // TODO: implement interrupt handling, signal errors + // ignored } diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/appl_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/appl_rffi.c new file mode 100644 index 0000000000000000000000000000000000000000..5ebdbc607dac1ec9eea0b17891b24be47328121f --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/appl_rffi.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017, 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. + */ + +#include <rffiutils.h> + +extern void dqrdc2_(double *x, int *ldx, int *n, int *p, double *tol, int *rank, double *qraux, int* pivot, double *work); +extern void dqrcf_(double *x, int *n, int *k, double *qraux, double *y, int *ny, double *b, int* info); +extern void dqrls_(double *x, int *n, int *p, double *y, int *ny, double *tol, double *b, double *rsd, double *qty, int *k, int *jpvt, double *qraux, double *work); + +void call_dqrdc2(double *x, int ldx, int n, int p, double tol, int *rank, double *qraux, int* pivot, double *work) { + dqrdc2_(x, &ldx, &n, &p, &tol, rank, qraux, pivot, work); +} + +void call_dqrcf(double *x, int n, int k, double *qraux, double *y, int ny, double *b, int* info) { + dqrcf_(x, &n, &k, qraux, y, &ny, b, info); +} + +void call_dqrls(double *x, int n, int p, double *y, int ny, double tol, double *b, double *rsd, double *qty, int *k, int *jpvt, double *qraux, double *work) { + dqrls_(x, &n, &p, y, &ny, &tol, b, rsd, qty, k, jpvt, qraux, work); +} diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/base_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/base_rffi.c new file mode 100644 index 0000000000000000000000000000000000000000..93188c9e9e9b6d841ce639ad02e3772ab316eaf6 --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/base_rffi.c @@ -0,0 +1,71 @@ +/* + * 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 + * 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. + */ +#include <rffiutils.h> + +#include <sys/types.h> +#include <unistd.h> +#include <sys/stat.h> +#include <glob.h> +#include <sys/utsname.h> +#include <errno.h> + + +void call_uname(void (*call_uname_setfields)(char *sysname, char *release, char *version, char *machine, char *nodename)) { + struct utsname name; + + uname(&name); + call_uname_setfields(name.sysname, name.release, name.version, name.machine, name.nodename); +} + +void call_glob(char *pattern, void *closure) { + void (*call_addpath)(char *path) = closure; + + glob_t globstruct; + int rc = glob(pattern, 0, NULL, &globstruct); + if (rc == 0) { + int i; + for (i = 0; i < globstruct.gl_pathc; i++) { + char *path = globstruct.gl_pathv[i]; + call_addpath(path); + } + } +} + +void call_readlink(void (*call_setresult)(char *link, int cerrno), char *path) { + char *link = NULL; + int cerrno = 0; + char buf[4096]; + int len = readlink(path, buf, 4096); + if (len == -1) { + cerrno = errno; + } else { + buf[len] = 0; + link = buf; + } + call_setresult(link, cerrno); +} + +void call_strtol(void (*call_setresult)(long result, int cerrno), char *s, int base) { + long rc = strtol(s, NULL, base); + call_setresult(rc, errno); +} diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/lapack_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/lapack_rffi.c new file mode 100644 index 0000000000000000000000000000000000000000..17d0589252ae023aebe08722a207ec989f4a4746 --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/lapack_rffi.c @@ -0,0 +1,136 @@ +/* + * 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. + */ + +#include <rffiutils.h> + +extern void ilaver_(int *major, int *minor, int *patch); + +void call_ilaver(int* version) { + int major; + int minor; + int patch; + ilaver_(&major, &minor, &patch); + version[0] = major; + version[1] = minor; + version[2] = patch; +} + +extern int dgeev_(char *jobVL, char *jobVR, int *n, double *a, int *lda, double *wr, double *wi, double *vl, int *ldvl, double *vr, int *ldvr, double *work, int *lwork, int *info); + +int call_dgeev(char jobVL, char jobVR, int n, double *a, int lda, double *wr, double *wi, double *vl, int ldvl, double *vr, int ldvr, double *work, int lwork) { + int info; + dgeev_(&jobVL, &jobVR, &n, a, &lda, wr, wi, vl, &ldvl, vr, &ldvr, work, &lwork, &info); + return info; +} + +extern int dgeqp3_(int *m, int *n, double *a, int *lda, int *jpvt, double *tau, double *work, int *lwork, int *info); + + +int call_dgeqp3(int m, int n, double *a, int lda, int *jpvt, double *tau, double *work, int lwork) { + int info; + dgeqp3_(&m, &n, a, &lda, jpvt, tau, work, &lwork, &info); + return info; +} + +extern int dormqr_(char *side, char *trans, int *m, int *n, int *k, double *a, int *lda, double *tau, double *c, int *ldc, double *work, int *lwork, int *info); + +int call_dormqr(char side, char trans, int m, int n, int k, double *a, int lda, double *tau, double *c, int ldc, double *work, int lwork) { + int info; + dormqr_(&side, &trans, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info); + return info; +} + +extern int dtrtrs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, int *info); + + +int call_dtrtrs(char uplo, char trans, char diag, int n, int nrhs, double *a, int lda, double *b, int ldb) { + int info; + dtrtrs_(&uplo, &trans, &diag, &n, &nrhs, a, &lda, b, &ldb, &info); + return info; +} + +extern int dgetrf_(int *m, int *n, double *a, int *lda, int *ipiv, int *info); + +int call_dgetrf(int m, int n, double *a, int lda, int *ipiv) { + int info; + dgetrf_(&m, &n, a, &lda, ipiv, &info); + return info; +} + +extern int dpotrf_(char *uplo, int *n, double *a, int *lda, int *info); + +int call_dpotrf(char uplo, int n, double *a, int lda) { + int info; + dpotrf_(&uplo, &n, a, &lda, &info); + return info; +} + +extern int dpotri_(char *uplo, int *n, double *a, int *lda, int *info); + +int call_dpotri(char uplo, int n, double *a, int lda) { + int info; + dpotri_(&uplo, &n, a, &lda, &info); + return info; +} + +extern int dpstrf_(char *uplo, int *n, double *a, int *lda, int *piv, int *rank, double *tol, double *work, int *info); + +int call_dpstrf(char uplo, int n, double *a, int lda, int *piv, int *rank, double tol, double *work) { + int info; + dpstrf_(&uplo, &n, a, &lda, piv, rank, &tol, work, &info); + return info; +} + +extern int dgesv_(int *n, int *nrhs, double *a, int *lda, int *ipiv, double *b, int *ldb, int *info); + +int call_dgesv(int n, int nrhs, double *a, int lda, int *ipiv, double *b, int ldb) { + int info; + dgesv_(&n, &nrhs, a, &lda, ipiv, b, &ldb, &info); + return info; +} + +extern double dlange_(char *norm, int *m, int *n, double *a, int *lda, double *work); + +double call_dlange(char norm, int m, int n, double *a, int lda, double *work) { + double info = dlange_(&norm, &m, &n, a, &lda, work); + return info; +} + +extern int dgecon_(char *norm, int *n, double *a, int *lda, double *anorm, double *rcond, double *work, int *iwork, int *info); + +int call_dgecon(char norm, int n, double *a, int lda, double anorm, double *rcond, double *work, int *iwork) { + int info; + dgecon_(&norm, &n, a, &lda, &anorm, rcond, work, iwork, &info); + return info; +} + +extern int dsyevr_(char *jobz, char *range, char *uplo, int *n, double* a, int *lda, double *vl, double *vu, int *il, int *iu, double *abstol, int* m, double* w, + double* z, int *ldz, int* isuppz, double* work, int *lwork, int* iwork, int *liwork, int* info); + +int call_dsyevr(char jobz, char range, char uplo, int n, double *a, int lda, double vl, double vu, int il, int iu, double abstol, int *m, double *w, + double *z, int ldz, int *isuppz, double *work, int lwork, int *iwork, int liwork) { + int info; + dsyevr_(&jobz, &range, &uplo, &n, a, &lda, &vl, &vu, &il, &iu, &abstol, m, w, + z, &ldz, isuppz, work, &lwork, iwork, &liwork, &info); + return info; +} diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/misc_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/misc_rffi.c new file mode 100644 index 0000000000000000000000000000000000000000..f5ccdf078a392ded6981cb6032556e655d169c39 --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/misc_rffi.c @@ -0,0 +1,50 @@ +/* + * 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. + */ + +#include <rffiutils.h> + +double exactSumFunc(double* contents, int length, int hasNa, int naRm) { + + long double sum = 0; + int i = 0; + if (!hasNa) { + for (; i < length - 3; i+= 4) { + sum += contents[i]; + sum += contents[i + 1]; + sum += contents[i + 2]; + sum += contents[i + 3]; + } + } + for (; i < length; i++) { + double value = contents[i]; + if (R_IsNA(value)) { + if (!naRm) { + return R_NaReal; + } + } else { + sum += value; + } + } + + return sum; +} diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/pcre_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/pcre_rffi.c new file mode 100644 index 0000000000000000000000000000000000000000..28be2cb058f1e36c093d08b4c7d4a8c07372324b --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/pcre_rffi.c @@ -0,0 +1,65 @@ +/* + * 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) 1995, 1996 Robert Gentleman and Ross Ihaka + * Copyright (c) 1997-2015, The R Core Team + * Copyright (c) 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +#include <rffiutils.h> + +#define PCRE_INFO_CAPTURECOUNT 2 +#define PCRE_INFO_NAMEENTRYSIZE 7 +#define PCRE_INFO_NAMECOUNT 8 +#define PCRE_INFO_NAMETABLE 9 + +//char *pcre_maketables(); +void *pcre_compile(char *pattern, int options, char **errorMessage, int *errOffset, char *tables); +//int pcre_exec(void *code, void *extra, char* subject, int subjectLength, int startOffset, int options, int *ovector, int ovecSize); +int pcre_fullinfo(void *code, void *extra, int what, void *where); +//void pcre_free(void *code); + +void call_compile(void *closure, char *pattern, int options, long tables) { + void (*call_makeresult)(long result, char *errMsg, int errOffset) = closure; + char *errorMessage; + int errOffset; + void *pcre_result = pcre_compile(pattern, options, &errorMessage, &errOffset, (char*) tables); + call_makeresult((long) pcre_result, errorMessage, errOffset); +} + +int call_getcapturecount(long code, long extra) { + int captureCount; + int rc = pcre_fullinfo((void*) code, (void*) extra, PCRE_INFO_CAPTURECOUNT, &captureCount); + return rc < 0 ? rc : captureCount; +} + +int call_getcapturenames(void *closure, long code, long extra) { + void (*call_setcapturename)(int i, char *name) = closure; + int nameCount; + int nameEntrySize; + char* nameTable; + int res; + res = pcre_fullinfo((void*) code, (void*) extra, PCRE_INFO_NAMECOUNT, &nameCount); + if (res < 0) { + return res; + } + res = pcre_fullinfo((void*) code, (void*) extra, PCRE_INFO_NAMEENTRYSIZE, &nameEntrySize); + if (res < 0) { + return res; + } + res = pcre_fullinfo((void*) code, (void*) extra, PCRE_INFO_NAMETABLE, &nameTable); + if (res < 0) { + return res; + } + // from GNU R's grep.c + for(int i = 0; i < nameCount; i++) { + char* entry = nameTable + nameEntrySize * i; + int captureNum = (entry[0] << 8) + entry[1] - 1; + call_setcapturename(captureNum, entry + 2); + } + return res; + +} diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacks.h b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacks.h new file mode 100644 index 0000000000000000000000000000000000000000..94d50549cc5151b44e1bb62db7633a4b59258ddf --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacks.h @@ -0,0 +1,282 @@ +/* + * 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 + * 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. + */ +#ifndef CALLBACKS_H +#define CALLBACKS_H + +#include "rffi_callbacksindex.h" + +extern void* callbacks[]; + +// This is the complete set , including those not yet implemented + +typedef SEXP (*call_Rf_ScalarInteger)(int value); +typedef SEXP (*call_Rf_ScalarReal)(double value); +typedef SEXP (*call_Rf_ScalarString)(SEXP value); +typedef SEXP (*call_Rf_ScalarLogical)(int value); +typedef SEXP (*call_Rf_allocVector)(SEXPTYPE t, R_xlen_t len); +typedef SEXP (*call_Rf_allocArray)(SEXPTYPE t, SEXP dims); +typedef SEXP (*call_Rf_alloc3DArray)(SEXPTYPE t, int x, int y, int z); +typedef SEXP (*call_Rf_allocMatrix)(SEXPTYPE mode, int nrow, int ncol); +typedef SEXP (*call_Rf_allocList)(int x); +typedef SEXP (*call_Rf_allocSExp)(SEXPTYPE t); +typedef SEXP (*call_Rf_cons)(SEXP car, SEXP cdr); +typedef void (*call_Rf_defineVar)(SEXP symbol, SEXP value, SEXP rho); +typedef void (*call_Rf_setVar)(SEXP x, SEXP y, SEXP z); +typedef SEXP (*call_Rf_dimgets)(SEXP x, SEXP y); +typedef SEXP (*call_Rf_dimnamesgets)(SEXP x, SEXP y); +typedef SEXP (*call_Rf_eval)(SEXP expr, SEXP env); +typedef SEXP (*call_Rf_findFun)(SEXP symbol, SEXP rho); +typedef SEXP (*call_Rf_findVar)(SEXP sym, SEXP rho); +typedef SEXP (*call_Rf_findVarInFrame)(SEXP rho, SEXP sym); +typedef SEXP (*call_Rf_findVarInFrame3)(SEXP rho, SEXP sym, Rboolean b); +typedef SEXP (*call_Rf_getAttrib)(SEXP vec, SEXP name); +typedef SEXP (*call_Rf_GetOption1)(SEXP tag); +typedef SEXP (*call_Rf_setAttrib)(SEXP vec, SEXP name, SEXP val); +typedef SEXP (*call_Rf_duplicate)(SEXP x, int v); +typedef SEXP (*call_Rf_shallow_duplicate)(SEXP x); +typedef SEXP (*call_Rf_coerceVector)(SEXP x, SEXPTYPE mode); +typedef R_xlen_t (*call_Rf_any_duplicated)(SEXP x, Rboolean from_last); +typedef SEXP (*call_Rf_duplicated)(SEXP x, Rboolean y); +typedef SEXP (*call_Rf_applyClosure)(SEXP x, SEXP y, SEXP z, SEXP a, SEXP b); +typedef void (*call_Rf_copyMostAttrib)(SEXP x, SEXP y); +typedef void (*call_Rf_copyVector)(SEXP x, SEXP y); +typedef int (*call_Rf_countContexts)(int x, int y); +typedef Rboolean (*call_Rf_inherits)(SEXP x, const char * klass); +typedef Rboolean (*call_Rf_isReal)(SEXP x); +typedef Rboolean (*call_Rf_isSymbol)(SEXP x); +typedef Rboolean (*call_Rf_isComplex)(SEXP x); +typedef Rboolean (*call_Rf_isEnvironment)(SEXP x); +typedef Rboolean (*call_Rf_isExpression)(SEXP x); +typedef Rboolean (*call_Rf_isLogical)(SEXP x); +typedef Rboolean (*call_Rf_isObject)(SEXP s); +typedef void (*call_Rf_PrintValue)(SEXP x); +typedef SEXP (*call_Rf_install)(const char *name); +typedef SEXP (*call_Rf_installChar)(SEXP charsxp); +typedef Rboolean (*call_Rf_isNull)(SEXP s); +typedef Rboolean (*call_Rf_isString)(SEXP s); +typedef Rboolean (*call_R_cycle_detected)(SEXP s, SEXP child); +typedef cetype_t (*call_Rf_getCharCE)(SEXP x); +typedef SEXP (*call_Rf_mkChar)(const char *x); +typedef SEXP (*call_Rf_mkCharCE)(const char *x, cetype_t y); +typedef SEXP (*call_Rf_mkCharLen)(const char *x, int y); +typedef SEXP (*call_Rf_mkCharLenCE)(const char *x, int len, cetype_t enc); +typedef const char * (*call_Rf_reEnc)(const char *x, cetype_t ce_in, cetype_t ce_out, int subst); +typedef SEXP (*call_Rf_mkString)(const char *s); +typedef int (*call_Rf_ncols)(SEXP x); +typedef int (*call_Rf_nrows)(SEXP x); +typedef SEXP (*call_Rf_protect)(SEXP x); +typedef void (*call_Rf_unprotect)(int x); +typedef void (*call_R_ProtectWithIndex)(SEXP x, PROTECT_INDEX *y); +typedef void (*call_R_Reprotect)(SEXP x, PROTECT_INDEX y); +typedef void (*call_Rf_unprotect_ptr)(SEXP x); +typedef void (*call_Rf_error)(const char *format, ...); +typedef void (*call_Rf_errorcall)(SEXP x, const char *format, ...); +typedef void (*call_Rf_warningcall)(SEXP x, const char *format, ...); +typedef void (*call_Rf_warning)(const char *format, ...); +typedef void (*call_Rprintf)(const char *format, ...); +typedef void (*call_Rvprintf)(const char *format, va_list args); +typedef void (*call_REvprintf)(const char *format, va_list args); +typedef void (*call_R_FlushConsole)(void); +typedef void (*call_R_ProcessEvents)(void); +typedef SEXP (*call_R_NewHashedEnv)(SEXP parent, SEXP size); +typedef SEXP (*call_Rf_classgets)(SEXP vec, SEXP klass); +typedef const char *(*call_Rf_translateChar)(SEXP x); +typedef const char *(*call_Rf_translateChar0)(SEXP x); +typedef const char *(*call_Rf_translateCharUTF8)(SEXP x); +typedef SEXP (*call_Rf_lengthgets)(SEXP x, R_len_t y); +typedef SEXP (*call_Rf_xlengthgets)(SEXP x, R_xlen_t y); +typedef SEXP (*call_R_lsInternal)(SEXP env, Rboolean all); +typedef SEXP (*call_R_lsInternal3)(SEXP env, Rboolean all, Rboolean sorted); +typedef SEXP (*call_Rf_namesgets)(SEXP x, SEXP y); +typedef SEXP (*call_TAG)(SEXP e); +typedef SEXP (*call_PRINTNAME)(SEXP e); +typedef SEXP (*call_CAR)(SEXP e); +typedef SEXP (*call_CDR)(SEXP e); +typedef SEXP (*call_CAAR)(SEXP e); +typedef SEXP (*call_CDAR)(SEXP e); +typedef SEXP (*call_CADR)(SEXP e); +typedef SEXP (*call_CDDR)(SEXP e); +typedef SEXP (*call_CDDDR)(SEXP e); +typedef SEXP (*call_CADDR)(SEXP e); +typedef SEXP (*call_CADDDR)(SEXP e); +typedef SEXP (*call_CAD4R)(SEXP e); +typedef int (*call_MISSING)(SEXP x); +typedef void (*call_SET_MISSING)(SEXP x, int v); +typedef void (*call_SET_TAG)(SEXP x, SEXP y); +typedef SEXP (*call_SETCAR)(SEXP x, SEXP y); +typedef SEXP (*call_SETCDR)(SEXP x, SEXP y); +typedef SEXP (*call_SETCADR)(SEXP x, SEXP y); +typedef SEXP (*call_SETCADDR)(SEXP x, SEXP y); +typedef SEXP (*call_SETCADDDR)(SEXP x, SEXP y); +typedef SEXP (*call_SETCAD4R)(SEXP e, SEXP y); +typedef SEXP (*call_FORMALS)(SEXP x); +typedef SEXP (*call_BODY)(SEXP x); +typedef SEXP (*call_CLOENV)(SEXP x); +typedef int (*call_RDEBUG)(SEXP x); +typedef int (*call_RSTEP)(SEXP x); +typedef int (*call_RTRACE)(SEXP x); +typedef void (*call_SET_RDEBUG)(SEXP x, int v); +typedef void (*call_SET_RSTEP)(SEXP x, int v); +typedef void (*call_SET_RTRACE)(SEXP x, int v); +typedef void (*call_SET_FORMALS)(SEXP x, SEXP v); +typedef void (*call_SET_BODY)(SEXP x, SEXP v); +typedef void (*call_SET_CLOENV)(SEXP x, SEXP v); +typedef SEXP (*call_SYMVALUE)(SEXP x); +typedef SEXP (*call_INTERNAL)(SEXP x); +typedef int (*call_DDVAL)(SEXP x); +typedef void (*call_SET_DDVAL)(SEXP x, int v); +typedef void (*call_SET_SYMVALUE)(SEXP x, SEXP v); +typedef void (*call_SET_INTERNAL)(SEXP x, SEXP v); +typedef SEXP (*call_FRAME)(SEXP x); +typedef SEXP (*call_ENCLOS)(SEXP x); +typedef SEXP (*call_HASHTAB)(SEXP x); +typedef int (*call_ENVFLAGS)(SEXP x); +typedef void (*call_SET_ENVFLAGS)(SEXP x, int v); +typedef void (*call_SET_FRAME)(SEXP x, SEXP v); +typedef void (*call_SET_ENCLOS)(SEXP x, SEXP v); +typedef void (*call_SET_HASHTAB)(SEXP x, SEXP v); +typedef SEXP (*call_PRCODE)(SEXP x); +typedef SEXP (*call_PRENV)(SEXP x); +typedef SEXP (*call_PRVALUE)(SEXP x); +typedef int (*call_PRSEEN)(SEXP x); +typedef void (*call_SET_PRSEEN)(SEXP x, int v); +typedef void (*call_SET_PRENV)(SEXP x, SEXP v); +typedef void (*call_SET_PRVALUE)(SEXP x, SEXP v); +typedef void (*call_SET_PRCODE)(SEXP x, SEXP v); +typedef int (*call_LENGTH)(SEXP x); +typedef int (*call_TRUELENGTH)(SEXP x); +typedef void (*call_SETLENGTH)(SEXP x, int v); +typedef void (*call_SET_TRUELENGTH)(SEXP x, int v); +typedef R_xlen_t (*call_XLENGTH)(SEXP x); +typedef R_xlen_t (*call_XTRUELENGTH)(SEXP x); +typedef int (*call_IS_LONG_VEC)(SEXP x); +typedef int (*call_LEVELS)(SEXP x); +typedef int (*call_SETLEVELS)(SEXP x, int v); +typedef int *(*call_LOGICAL)(SEXP x); +typedef int *(*call_INTEGER)(SEXP x); +typedef Rbyte *(*call_RAW)(SEXP x); +typedef double *(*call_REAL)(SEXP x); +typedef Rcomplex *(*call_COMPLEX)(SEXP x); +typedef SEXP (*call_STRING_ELT)(SEXP x, R_xlen_t i); +typedef SEXP (*call_VECTOR_ELT)(SEXP x, R_xlen_t i); +typedef void (*call_SET_STRING_ELT)(SEXP x, R_xlen_t i, SEXP v); +typedef SEXP (*call_SET_VECTOR_ELT)(SEXP x, R_xlen_t i, SEXP v); +typedef SEXP *(*call_STRING_PTR)(SEXP x); +typedef SEXP *(*call_VECTOR_PTR)(SEXP x); +typedef SEXP (*call_Rf_asChar)(SEXP x); +typedef SEXP (*call_Rf_PairToVectorList)(SEXP x); +typedef SEXP (*call_Rf_VectorToPairList)(SEXP x); +typedef SEXP (*call_Rf_asCharacterFactor)(SEXP x); +typedef int (*call_Rf_asLogical)(SEXP x); +typedef int (*call_Rf_asInteger)(SEXP x); +typedef double (*call_Rf_asReal)(SEXP x); +typedef Rcomplex (*call_Rf_asComplex)(SEXP x); +typedef int (*call_TYPEOF)(SEXP x); +typedef SEXP (*call_ATTRIB)(SEXP x); +typedef int (*call_OBJECT)(SEXP x); +typedef int (*call_MARK)(SEXP x); +typedef int (*call_NAMED)(SEXP x); +typedef int (*call_REFCNT)(SEXP x); +typedef void (*call_SET_OBJECT)(SEXP x, int v); +typedef void (*call_SET_TYPEOF)(SEXP x, int v); +typedef SEXP (*call_SET_TYPEOF_FASTR)(SEXP x, int v); +typedef void (*call_SET_NAMED)(SEXP x, int v); +typedef void (*call_SET_ATTRIB)(SEXP x, SEXP v); +typedef void (*call_DUPLICATE_ATTRIB)(SEXP to, SEXP from); +typedef int (*call_IS_S4_OBJECT)(SEXP x); +typedef void (*call_SET_S4_OBJECT)(SEXP x); +typedef void (*call_UNSET_S4_OBJECT)(SEXP x); +typedef Rboolean (*call_R_ToplevelExec)(void (*fun)(void *), void *data); +typedef void (*call_R_RestoreHashCount)(SEXP rho); +typedef Rboolean (*call_R_IsPackageEnv)(SEXP rho); +typedef SEXP (*call_R_PackageEnvName)(SEXP rho); +typedef SEXP (*call_R_FindPackageEnv)(SEXP info); +typedef Rboolean (*call_R_IsNamespaceEnv)(SEXP rho); +typedef SEXP (*call_R_NamespaceEnvSpec)(SEXP rho); +typedef SEXP (*call_R_FindNamespace)(SEXP info); +typedef void (*call_R_LockEnvironment)(SEXP env, Rboolean bindings); +typedef Rboolean (*call_R_EnvironmentIsLocked)(SEXP env); +typedef void (*call_R_LockBinding)(SEXP sym, SEXP env); +typedef void (*call_R_unLockBinding)(SEXP sym, SEXP env); +typedef void (*call_R_MakeActiveBinding)(SEXP sym, SEXP fun, SEXP env); +typedef Rboolean (*call_R_BindingIsLocked)(SEXP sym, SEXP env); +typedef Rboolean (*call_R_BindingIsActive)(SEXP sym, SEXP env); +typedef Rboolean (*call_R_HasFancyBindings)(SEXP rho); +typedef Rboolean (*call_Rf_isS4)(SEXP x); +typedef SEXP (*call_Rf_asS4)(SEXP x, Rboolean b, int i); +typedef SEXP (*call_R_tryEval)(SEXP x, SEXP y, int *ErrorOccurred); +typedef SEXP (*call_R_tryEvalSilent)(SEXP x, SEXP y, int *ErrorOccurred); +typedef double (*call_R_atof)(const char *str); +typedef double (*call_R_strtod)(const char *c, char **end); +typedef SEXP (*call_R_PromiseExpr)(SEXP x); +typedef SEXP (*call_R_ClosureExpr)(SEXP x); +typedef SEXP (*call_R_forceAndCall)(SEXP e, int n, SEXP rho); +typedef SEXP (*call_R_MakeExternalPtr)(void *p, SEXP tag, SEXP prot); +typedef void *(*call_R_ExternalPtrAddr)(SEXP s); +typedef SEXP (*call_R_ExternalPtrTag)(SEXP s); +typedef SEXP (*call_R_ExternalPtrProtected)(SEXP s); +typedef void (*call_R_SetExternalPtrAddr)(SEXP s, void *p); +typedef void (*call_R_SetExternalPtrTag)(SEXP s, SEXP tag); +typedef void (*call_R_SetExternalPtrProtected)(SEXP s, SEXP p); +typedef void (*call_R_ClearExternalPtr)(SEXP s); +typedef void (*call_R_RegisterFinalizer)(SEXP s, SEXP fun); +typedef void (*call_R_RegisterCFinalizer)(SEXP s, R_CFinalizer_t fun); +typedef void (*call_R_RegisterFinalizerEx)(SEXP s, SEXP fun, Rboolean onexit); +typedef void (*call_R_RegisterCFinalizerEx)(SEXP s, R_CFinalizer_t fun, Rboolean onexit); +typedef void (*call_R_RunPendingFinalizers)(void); +typedef SEXP (*call_R_MakeWeakRef)(SEXP key, SEXP val, SEXP fin, Rboolean onexit); +typedef SEXP (*call_R_MakeWeakRefC)(SEXP key, SEXP val, R_CFinalizer_t fin, Rboolean onexit); +typedef SEXP (*call_R_WeakRefKey)(SEXP w); +typedef SEXP (*call_R_WeakRefValue)(SEXP w); +typedef void (*call_R_RunWeakRefFinalizer)(SEXP w); +typedef SEXP (*call_R_do_slot)(SEXP obj, SEXP name); +typedef SEXP (*call_R_do_slot_assign)(SEXP obj, SEXP name, SEXP value); +typedef int (*call_R_has_slot)(SEXP obj, SEXP name); +typedef SEXP (*call_R_do_MAKE_CLASS)(const char *what); +typedef SEXP (*call_R_getClassDef )(const char *what); +typedef SEXP (*call_R_do_new_object)(SEXP class_def); +typedef int (*call_R_check_class_and_super)(SEXP x, const char **valid, SEXP rho); +typedef int (*call_R_check_class_etc )(SEXP x, const char **valid); +typedef SEXP (*call_R_PreserveObject)(SEXP x); +typedef void (*call_R_ReleaseObject)(SEXP x); +typedef void (*call_R_dot_Last)(void); +typedef Rboolean (*call_R_compute_identical)(SEXP x, SEXP y, int flags); +typedef void (*call_Rf_copyListMatrix)(SEXP s, SEXP t, Rboolean byrow); +typedef void (*call_Rf_copyMatrix)(SEXP s, SEXP t, Rboolean byrow); +typedef void (*call_GetRNGstate)(); +typedef void (*call_PutRNGstate)(); +typedef SEXP (*call_R_BaseEnv)(); +typedef SEXP (*call_R_BaseNamespace)(); +typedef SEXP (*call_R_MethodsNamespace)(); +typedef SEXP (*call_R_GlobalEnv)(); +typedef SEXP (*call_R_NamespaceRegistry)(); +typedef SEXP (*call_R_Interactive)(); +typedef SEXP (*call_R_GlobalContext)(); +typedef SEXP (*call_R_CHAR)(SEXP x); +typedef char *(*call_R_HomeDir)(); +typedef void (*call_R_CleanUp)(int sa, int status, int runlast); +typedef void (*call_Rf_gsetVar)(SEXP symbol, SEXP value, SEXP rho); +typedef double (*call_unif_rand)(); + +#endif + diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacksindex.h b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacksindex.h new file mode 100644 index 0000000000000000000000000000000000000000..0a457d98f0c486ff3797c96dbc47ac5b28473c69 --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacksindex.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2017, 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. + */ + +// TODO This file should be generated automatically from RFFIUpCallMethod.main + +#ifndef CALLBACKSINDEX_H +#define CALLBACKSINDEX_H + +#define CADDR_x 0 +#define CADR_x 1 +#define CAR_x 2 +#define CDDR_x 3 +#define CDR_x 4 +#define DUPLICATE_ATTRIB_x 5 +#define ENCLOS_x 6 +#define GetRNGstate_x 7 +#define INTEGER_x 8 +#define IS_S4_OBJECT_x 9 +#define SET_S4_OBJECT_x 10 +#define UNSET_S4_OBJECT_x 11 +#define LENGTH_x 12 +#define LOGICAL_x 13 +#define NAMED_x 14 +#define OBJECT_x 15 +#define PRCODE_x 16 +#define PRENV_x 17 +#define PRINTNAME_x 18 +#define PRSEEN_x 19 +#define PRVALUE_x 20 +#define PutRNGstate_x 21 +#define RAW_x 22 +#define RDEBUG_x 23 +#define REAL_x 24 +#define RSTEP_x 25 +#define R_BaseEnv_x 26 +#define R_BaseNamespace_x 27 +#define R_BindingIsLocked_x 28 +#define R_CHAR_x 29 +#define R_CleanUp_x 30 +#define R_ExternalPtrAddr_x 31 +#define R_ExternalPtrProtected_x 32 +#define R_ExternalPtrTag_x 33 +#define R_FindNamespace_x 34 +#define R_GetConnection_x 35 +#define R_GlobalContext_x 36 +#define R_GlobalEnv_x 37 +#define R_HomeDir_x 38 +#define R_Interactive_x 39 +#define R_MakeExternalPtr_x 40 +#define R_MethodsNamespace_x 41 +#define R_NamespaceRegistry_x 42 +#define R_NewHashedEnv_x 43 +#define R_ParseVector_x 44 +#define R_PromiseExpr_x 45 +#define R_ReadConnection_x 46 +#define R_SetExternalPtrAddr_x 47 +#define R_SetExternalPtrProtected_x 48 +#define R_SetExternalPtrTag_x 49 +#define R_ToplevelExec_x 50 +#define R_WriteConnection_x 51 +#define R_compute_identical_x 52 +#define R_do_MAKE_CLASS_x 53 +#define R_do_new_object_x 54 +#define R_do_slot_x 55 +#define R_do_slot_assign_x 56 +#define R_getContextCall_x 57 +#define R_getContextEnv_x 58 +#define R_getContextFun_x 59 +#define R_getContextSrcRef_x 60 +#define R_getGlobalFunctionContext_x 61 +#define R_getParentFunctionContext_x 62 +#define R_insideBrowser_x 63 +#define R_isEqual_x 64 +#define R_isGlobal_x 65 +#define R_lsInternal3_x 66 +#define R_new_custom_connection_x 67 +#define R_tryEval_x 68 +#define Rf_GetOption1_x 69 +#define Rf_PairToVectorList_x 70 +#define Rf_ScalarDouble_x 71 +#define Rf_ScalarInteger_x 72 +#define Rf_ScalarLogical_x 73 +#define Rf_ScalarString_x 74 +#define Rf_allocArray_x 75 +#define Rf_allocMatrix_x 76 +#define Rf_allocVector_x 77 +#define Rf_any_duplicated_x 78 +#define Rf_asChar_x 79 +#define Rf_asInteger_x 80 +#define Rf_asLogical_x 81 +#define Rf_asReal_x 82 +#define Rf_classgets_x 83 +#define Rf_coerceVector_x 84 +#define Rf_cons_x 85 +#define Rf_copyListMatrix_x 86 +#define Rf_copyMatrix_x 87 +#define Rf_defineVar_x 88 +#define Rf_duplicate_x 89 +#define Rf_error_x 90 +#define Rf_eval_x 91 +#define Rf_findVar_x 92 +#define Rf_findVarInFrame_x 93 +#define Rf_findVarInFrame3_x 94 +#define Rf_findFun_x 95 +#define Rf_getAttrib_x 96 +#define Rf_gsetVar_x 97 +#define Rf_inherits_x 98 +#define Rf_install_x 99 +#define Rf_installChar_x 100 +#define Rf_isNull_x 101 +#define Rf_isString_x 102 +#define Rf_lengthgets_x 103 +#define Rf_mkCharLenCE_x 104 +#define Rf_ncols_x 105 +#define Rf_nrows_x 106 +#define Rf_setAttrib_x 107 +#define Rf_warning_x 108 +#define Rf_warningcall_x 109 +#define Rprintf_x 110 +#define SETCADR_x 111 +#define SETCAR_x 112 +#define SETCDR_x 113 +#define SET_RDEBUG_x 114 +#define SET_RSTEP_x 115 +#define SET_STRING_ELT_x 116 +#define SET_SYMVALUE_x 117 +#define SET_TAG_x 118 +#define SET_TYPEOF_FASTR_x 119 +#define SET_VECTOR_ELT_x 120 +#define STRING_ELT_x 121 +#define SYMVALUE_x 122 +#define TAG_x 123 +#define TYPEOF_x 124 +#define VECTOR_ELT_x 125 +#define getConnectionClassString_x 126 +#define getOpenModeString_x 127 +#define getSummaryDescription_x 128 +#define isSeekable_x 129 +#define unif_rand_x 130 + +#define CALLBACK_TABLE_SIZE 131 + +#endif // CALLBACKSINDEX_H diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RInvisibleBuiltinNode.java b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.c similarity index 85% rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RInvisibleBuiltinNode.java rename to com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.c index 0577e23b3ad2b3a3ab42a87aaef40e0e2374005c..26a0c8bd183b73432de034c3033bb6e4d87398ec 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RInvisibleBuiltinNode.java +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 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 @@ -20,8 +20,10 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.nodes.builtin; - -public abstract class RInvisibleBuiltinNode extends RBuiltinNode { +#include <rffiutils.h> +void* unimplemented(char *f) { + printf("unimplemented %s\n", f); + exit(1); } + diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h new file mode 100644 index 0000000000000000000000000000000000000000..9a6c701305586f600b76a88a3df7753a2c1f20f3 --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h @@ -0,0 +1,40 @@ +/* + * 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 + * 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. + */ +#ifndef RFFIUTILS_H +#define RFFIUTILS_H + +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <Rinternals.h> +#include <rffi_callbacks.h> +#include <trufflenfi.h> + +extern void init_memory(); + +// use for an unimplemented API function +void *unimplemented(char *msg) __attribute__((noreturn)); +// use for any fatal error +void fatalError(char *msg) __attribute__((noreturn)); + +#endif diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c new file mode 100644 index 0000000000000000000000000000000000000000..a16e5c6a921b50c850bad242b11870c821fc39b7 --- /dev/null +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c @@ -0,0 +1,395 @@ +/* + * 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 + * 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. + */ +#include <string.h> +#include <Rinterface.h> +#include <trufflenfi.h> +#include <rffiutils.h> + +// Indices into RFFIVariables enum +// The commented out entries are not used as they are remapped +// as functions and the name clashes with the callback index for that +#define R_Home_x 0 +#define R_TempDir_x 1 +#define R_NilValue_x 2 +#define R_UnboundValue_x 3 +#define R_MissingArg_x 4 +//#define R_GlobalEnv_x 5 +#define R_EmptyEnv_x 6 +//#define R_BaseEnv_x 7 +//#define R_BaseNamespace_x 8 +//#define R_NamespaceRegistry_x 9 +#define R_Srcref_x 10 +#define R_Bracket2Symbol_x 11 +#define R_BracketSymbol_x 12 +#define R_BraceSymbol_x 13 +#define R_ClassSymbol_x 14 +#define R_DeviceSymbol_x 15 +#define R_DevicesSymbol_x 16 +#define R_DimNamesSymbol_x 17 +#define R_DimSymbol_x 18 +#define R_DollarSymbol_x 19 +#define R_DotsSymbol_x 20 +#define R_DropSymbol_x 21 +#define R_LastvalueSymbol_x 22 +#define R_LevelsSymbol_x 23 +#define R_ModeSymbol_x 24 +#define R_NameSymbol_x 25 +#define R_NamesSymbol_x 26 +#define R_NaRmSymbol_x 27 +#define R_PackageSymbol_x 28 +#define R_QuoteSymbol_x 29 +#define R_RowNamesSymbol_x 30 +#define R_SeedsSymbol_x 31 +#define R_SourceSymbol_x 32 +#define R_TspSymbol_x 33 +#define R_dot_defined_x 34 +#define R_dot_Method_x 35 +#define R_dot_target_x 36 +#define R_SrcrefSymbol_x 37 +#define R_SrcfileSymbol_x 38 +#define R_NaString_x 39 +#define R_NaN_x 40 +#define R_PosInf_x 41 +#define R_NegInf_x 42 +#define R_NaReal_x 43 +#define R_NaInt_x 44 +#define R_BlankString_x 45 +#define R_BlankScalarString_x 46 +#define R_BaseSymbol_x 47 +#define R_NamespaceEnvSymbol_x 48 +#define R_RestartToken_x 49 + +static const char *R_Home_static; +static const char *R_TempDir_static; +static SEXP R_EmptyEnv_static; +static SEXP R_Srcref_static; +static SEXP R_NilValue_static; +static SEXP R_UnboundValue_static; +static SEXP R_MissingArg_static; +static SEXP R_BaseSymbol_static; +static SEXP R_Bracket2Symbol_static; /* "[[" */ +static SEXP R_BracketSymbol_static; /* "[" */ +static SEXP R_BraceSymbol_static; /* "{" */ +static SEXP R_ClassSymbol_static; /* "class" */ +static SEXP R_DeviceSymbol_static; /* ".Device" */ +static SEXP R_DevicesSymbol_static; /* ".Devices" */ +static SEXP R_DimNamesSymbol_static; /* "dimnames" */ +static SEXP R_DimSymbol_static; /* "dim" */ +static SEXP R_DollarSymbol_static; /* "$" */ +static SEXP R_DotsSymbol_static; /* "..." */ +static SEXP R_DropSymbol_static; /* "drop" */ +static SEXP R_LastvalueSymbol_static; /* ".Last.value" */ +static SEXP R_LevelsSymbol_static; /* "levels" */ +static SEXP R_ModeSymbol_static; /* "mode" */ +static SEXP R_NameSymbol_static; /* "name" */ +static SEXP R_NamesSymbol_static; /* "names" */ +static SEXP R_NaRmSymbol_static; /* "na.rm" */ +static SEXP R_PackageSymbol_static; /* "package" */ +static SEXP R_QuoteSymbol_static; /* "quote" */ +static SEXP R_RowNamesSymbol_static; /* "row.names" */ +static SEXP R_SeedsSymbol_static; /* ".Random.seed" */ +static SEXP R_SourceSymbol_static; /* "source" */ +static SEXP R_TspSymbol_static; /* "tsp" */ +static SEXP R_dot_defined_static; /* ".defined" */ +static SEXP R_dot_Method_static; /* ".Method" */ +static SEXP R_dot_target_static; /* ".target" */ +static SEXP R_NaString_static; /* NA_STRING as a CHARSXP */ +static SEXP R_BlankString_static; /* "" as a CHARSXP */ +static SEXP R_BlankScalarString_static; /* "" as a STRSXP */ +static SEXP R_BaseSymbol_static; /* "base" as a SYMSXP */ +static SEXP R_NamespaceEnvSymbol_static; // ".__NAMESPACE__." + +// Symbols not part of public API but used in FastR tools implementation +static SEXP R_SrcrefSymbol_static; +static SEXP R_SrcfileSymbol_static; +static SEXP R_RestartToken_static; + +// Arith.h +double R_NaN; /* IEEE NaN */ +double R_PosInf; /* IEEE Inf */ +double R_NegInf; /* IEEE -Inf */ +double R_NaReal; /* NA_REAL: IEEE */ +int R_NaInt; /* NA_INTEGER:= INT_MIN currently */ + +// various ignored flags and variables nevertheless needed to resolve symbols +Rboolean R_Visible; +Rboolean R_interrupts_suspended; +int R_interrupts_pending; +Rboolean mbcslocale; +Rboolean useaqua; +char* OutDec = "."; +Rboolean utf8locale = FALSE; +Rboolean mbcslocale = FALSE; +Rboolean latin1locale = FALSE; +int R_dec_min_exponent = -308; +int max_contour_segments = 25000; + +// from sys-std.c +#include <R_ext/eventloop.h> + +static InputHandler BasicInputHandler = {2, -1, NULL}; +InputHandler *R_InputHandlers = &BasicInputHandler; + +char *FASTR_R_Home() { + return (char *) R_Home_static; +} + +char *FASTR_R_TempDir() { + return (char *) R_TempDir_static; +} + +SEXP FASTR_R_EmptyEnv() { + return R_EmptyEnv_static; +} + +SEXP FASTR_R_Srcref() { + return R_Srcref_static; +} + +SEXP FASTR_R_NilValue() { + return R_NilValue_static; +} + +SEXP FASTR_R_UnboundValue() { + return R_UnboundValue_static; +} + +SEXP FASTR_R_MissingArg() { + return R_MissingArg_static; +} + +SEXP FASTR_R_BaseSymbol() { + return R_BaseSymbol_static; +} + + +SEXP FASTR_R_BraceSymbol() { + return R_BraceSymbol_static; +} + +SEXP FASTR_R_Bracket2Symbol() { + return R_Bracket2Symbol_static; +} + +SEXP FASTR_R_BracketSymbol() { + return R_BracketSymbol_static; +} + +SEXP FASTR_R_ClassSymbol() { + return R_ClassSymbol_static; +} + +SEXP FASTR_R_DimNamesSymbol() { + return R_DimNamesSymbol_static; +} + +SEXP FASTR_R_DimSymbol() { + return R_DimSymbol_static; +} + + +SEXP FASTR_R_DollarSymbol() { + return R_DollarSymbol_static; +} + +SEXP FASTR_R_DotsSymbol() { + return R_DotsSymbol_static; +} + + +SEXP FASTR_R_DropSymbol() { + return R_DropSymbol_static; +} + +SEXP FASTR_R_LastvalueSymbol() { + return R_LastvalueSymbol_static; +} + + +SEXP FASTR_R_LevelsSymbol() { + return R_LevelsSymbol_static; +} + +SEXP FASTR_R_ModeSymbol() { + return R_ModeSymbol_static; +} + +SEXP FASTR_R_NaRmSymbol() { + return R_NaRmSymbol_static; +} + + +SEXP FASTR_R_NameSymbol() { + return R_NameSymbol_static; +} + +SEXP FASTR_R_NamesSymbol() { + return R_NamesSymbol_static; +} + + +SEXP FASTR_R_NamespaceEnvSymbol() { + return R_NamespaceEnvSymbol_static; +} + +SEXP FASTR_R_PackageSymbol() { + return R_PackageSymbol_static; +} + +SEXP FASTR_R_QuoteSymbol() { + return R_QuoteSymbol_static; +} + +SEXP FASTR_R_RowNamesSymbol() { + return R_RowNamesSymbol_static; +} + +SEXP FASTR_R_SeedsSymbol() { + return R_SeedsSymbol_static; +} + +SEXP FASTR_R_SourceSymbol() { + return R_SourceSymbol_static; +} + +SEXP FASTR_R_TspSymbol() { + return R_TspSymbol_static; +} + +SEXP FASTR_R_dot_defined() { + return R_dot_defined_static; +} + +SEXP FASTR_R_dot_Method() { + return R_dot_Method_static; +} + +SEXP FASTR_R_dot_target() { + return R_dot_target_static; +} + +SEXP FASTR_R_NaString() { + return R_NaString_static; +} + + +SEXP FASTR_R_BlankString() { + return R_BlankString_static; +} + +SEXP FASTR_R_BlankScalarString() { + return R_BlankScalarString_static; +} + +SEXP FASTR_R_DevicesSymbol() { + return R_DevicesSymbol_static; +} + +SEXP FASTR_R_DeviceSymbol() { + return R_DeviceSymbol_static; +} + +SEXP FASTR_R_SrcrefSymbol() { + return R_SrcrefSymbol_static; +} + +SEXP FASTR_R_SrcfileSymbol() { + return R_SrcfileSymbol_static; +} + +void Call_initvar_double(int index, double value) { + switch (index) { + case R_NaN_x: R_NaN = value; break; + } +} + +void Call_initvar_int(int index, int value) { + switch (index) { + case R_NaInt_x: R_NaInt = value; break; + case R_PosInf_x: R_PosInf = value; break; + case R_NegInf_x: R_NegInf = value; break; + case R_NaReal_x: R_NaReal = value; break; + } +} + +char *copystring(char *value) { + char *result = malloc(strlen(value) + 1); + strcpy(result, value); + return result; +} + +// value must be copied +void Call_initvar_string(int index, char *value) { + switch (index) { + case R_Home_x: R_Home_static = copystring(value); break; + case R_TempDir_x: R_TempDir_static = copystring(value); break; + } +} + +void Call_initvar_obj(int index, void* value) { + switch (index) { + case R_NilValue_x: R_NilValue_static = newObjectRef(value); break; + case R_UnboundValue_x: R_UnboundValue_static = newObjectRef(value); break; + case R_MissingArg_x: R_MissingArg_static = newObjectRef(value); break; +// case R_Srcref_x: R_Srcref_static = newObjectRef(value); break; + case R_EmptyEnv_x: R_EmptyEnv_static = newObjectRef(value); break; + case R_Bracket2Symbol_x: R_Bracket2Symbol_static = newObjectRef(value); break; + case R_BracketSymbol_x: R_BracketSymbol_static = newObjectRef(value); break; + case R_BraceSymbol_x: R_BraceSymbol_static = newObjectRef(value); break; + case R_ClassSymbol_x: R_ClassSymbol_static = newObjectRef(value); break; + case R_DeviceSymbol_x: R_DeviceSymbol_static = newObjectRef(value); break; + case R_DevicesSymbol_x: R_DevicesSymbol_static = newObjectRef(value); break; + case R_DimNamesSymbol_x: R_DimNamesSymbol_static = newObjectRef(value); break; + case R_DimSymbol_x: R_DimSymbol_static = newObjectRef(value); break; + case R_DollarSymbol_x: R_DollarSymbol_static = newObjectRef(value); break; + case R_DotsSymbol_x: R_DotsSymbol_static = newObjectRef(value); break; + case R_DropSymbol_x: R_DropSymbol_static = newObjectRef(value); break; + case R_LastvalueSymbol_x: R_LastvalueSymbol_static = newObjectRef(value); break; + case R_LevelsSymbol_x: R_LevelsSymbol_static = newObjectRef(value); break; + case R_ModeSymbol_x: R_ModeSymbol_static = newObjectRef(value); break; + case R_NameSymbol_x: R_NameSymbol_static = newObjectRef(value); break; + case R_NamesSymbol_x: R_NamesSymbol_static = newObjectRef(value); break; + case R_NaRmSymbol_x: R_NaRmSymbol_static = newObjectRef(value); break; + case R_PackageSymbol_x: R_PackageSymbol_static = newObjectRef(value); break; + case R_QuoteSymbol_x: R_QuoteSymbol_static = newObjectRef(value); break; + case R_RowNamesSymbol_x: R_RowNamesSymbol_static = newObjectRef(value); break; + case R_SeedsSymbol_x: R_SeedsSymbol_static = newObjectRef(value); break; + case R_SourceSymbol_x: R_SourceSymbol_static = newObjectRef(value); break; + case R_TspSymbol_x: R_TspSymbol_static = newObjectRef(value); break; + case R_dot_defined_x: R_dot_defined_static = newObjectRef(value); break; + case R_dot_Method_x: R_dot_Method_static = newObjectRef(value); break; + case R_dot_target_x: R_dot_target_static = newObjectRef(value); break; + case R_SrcrefSymbol_x: R_SrcrefSymbol_static = newObjectRef(value); break; + case R_SrcfileSymbol_x: R_SrcfileSymbol_static = newObjectRef(value); break; + case R_NaString_x: R_NaString_static = newObjectRef(value); break; + case R_BlankString_x: R_BlankString_static = newObjectRef(value); break; + case R_BlankScalarString_x: R_BlankString_static = newObjectRef(value); break; + case R_BaseSymbol_x: R_BaseSymbol_static = newObjectRef(value); break; + case R_NamespaceEnvSymbol_x: R_NamespaceEnvSymbol_static = newObjectRef(value); break; + // case R_RestartToken_x: R_RestartToken_static = newObjectRef(value); break; + default: + printf("Call_initvar_obj: unimplemented index %d\n", index); + exit(1); + } +} + diff --git a/com.oracle.truffle.r.native/gnur/Makefile.gnur b/com.oracle.truffle.r.native/gnur/Makefile.gnur index abc5c59b1227e8a21671fa957b3681d4588654a0..a6819b2a23e2fdb1dd3fc034318542e1e41717cd 100644 --- a/com.oracle.truffle.r.native/gnur/Makefile.gnur +++ b/com.oracle.truffle.r.native/gnur/Makefile.gnur @@ -40,12 +40,12 @@ OSNAME := $(shell uname) -ifdef FASTR_TRUFFLE_RFFI +ifeq ($(FASTR_RFFI),llvm) FC_DIR := $(abspath $(TOPDIR)/../mx.fastr/compilers) FASTR_COMPILERS := CC=$(FC_DIR)/fastr-cc FC=$(FC_DIR)/fastr-fc F77=$(FC_DIR)/fastr-fc CXX=$(FC_DIR)/fastr-c++ CXXCPP=$(FC_DIR)/fastr-cpp OBJC=$(FC_DIR)/fastr-cc endif -ifndef FASTR_TRUFFLE_RFFI +ifneq ($(FASTR_RFFI),llvm) # LLVM text parser and -g don't get on OPT_FLAGS := -g -O2 OPT_FLAGS := -O2 diff --git a/com.oracle.truffle.r.native/include/Makefile b/com.oracle.truffle.r.native/include/Makefile index 2de8932ab170d53b33ed31cf7968e09cc26b3fbe..b4b5ba423b5a53d0495714ace76d75e9cb9f7b17 100644 --- a/com.oracle.truffle.r.native/include/Makefile +++ b/com.oracle.truffle.r.native/include/Makefile @@ -37,7 +37,7 @@ R_EXT_HEADERS_TO_LINK := $(filter-out $(notdir $(R_EXT_HEADERS_LOCAL)),$(R_EXT_H R_HEADERS := $(wildcard $(GNUR_HOME)/include/*.h) R_HEADERS_FILENAMES := $(notdir $(R_HEADERS)) #$(info R_HEADERS_FILENAMES=$(R_HEADERS_FILENAMES)) -R_HEADERS_LOCAL := src/libintl.h src/Rinternals.h src/Rinterface.h +R_HEADERS_LOCAL := src/Rinternals.h src/Rinterface.h #$(info R_HEADERS_LOCAL=$(R_HEADERS_LOCAL))> R_HEADERS_TO_LINK := $(filter-out $(notdir $(R_HEADERS_LOCAL)),$(R_HEADERS_FILENAMES)) #$(info R_HEADERS_TO_LINK=$(R_HEADERS_TO_LINK)) @@ -47,7 +47,6 @@ all: linked linked: mkdir -p R_ext $(foreach file,$(R_HEADERS_TO_LINK),ln -sf $(GNUR_HOME)/include/$(file) $(file);) - ln -sf src/libintl.h mx edinclude $(GNUR_HOME)/include $(foreach file,$(R_EXT_HEADERS_TO_LINK),ln -sf $(GNUR_HOME)/include/R_ext/$(file) R_ext/$(file);) # cp $(R_EXT_HEADERS_LOCAL) R_ext diff --git a/com.oracle.truffle.r.native/include/src/libintl.h b/com.oracle.truffle.r.native/include/src/libintl.h deleted file mode 100644 index fab17ac780e37516a47cc8b0310cae7caa3a1baf..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.native/include/src/libintl.h +++ /dev/null @@ -1 +0,0 @@ -// Empty file diff --git a/com.oracle.truffle.r.native/library/base/Makefile b/com.oracle.truffle.r.native/library/base/Makefile index 6e57a6d5877a4affae10e63f2aeb15c2e9445403..9e56056560f802add59e270d8f8024f5ed39984f 100644 --- a/com.oracle.truffle.r.native/library/base/Makefile +++ b/com.oracle.truffle.r.native/library/base/Makefile @@ -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 @@ -21,4 +21,38 @@ # questions. # +ifeq ($(FASTR_RFFI),managed) +# lib.mk copies the GNU R library/base dir to the FastR library dir +# so we have to build the "uncompressed" variant of GNU R in the PRE phase. +LIB_PKG_PRE = pre.done +LIB_PKG_POST = post.done +CLEAN_PKG = clean.done +endif + include ../lib.mk + +ifeq ($(FASTR_RFFI),managed) +# The following changes GnuR's build script makebasedb.R so that it does not +# compress the lazy load database, then it (re)builds GnuR +pre.done: + cp $(GNUR_HOME)/src/library/base/makebasedb.R $(GNUR_HOME)/src/library/base/makebasedb.R.tmp + sed 's|compress = TRUE|compress = FALSE|g' $(GNUR_HOME)/src/library/base/makebasedb.R.tmp > $(GNUR_HOME)/src/library/base/makebasedb.R +# force a base rebuild + rm $(GNUR_HOME)/src/library/base/all.R + (cd $(GNUR_HOME); $(MAKE)) + touch pre.done + +# original base assumes that "base" DLL is loaded, we change it to check for that first +post.done: + sed 's|## populate C\/Fortran symbols|if (length(getLoadedDLLs()) > 0)|g' $(FASTR_LIBRARY_DIR)/base/R/base > $(FASTR_LIBRARY_DIR)/base/R/base.tmp + mv $(FASTR_LIBRARY_DIR)/base/R/base.tmp $(FASTR_LIBRARY_DIR)/base/R/base + mv $(GNUR_HOME)/src/library/base/makebasedb.R.tmp $(GNUR_HOME)/src/library/base/makebasedb.R +# force a base rebuild + rm $(GNUR_HOME)/src/library/base/all.R +# rebuild GNU R in compressed mode + (cd $(GNUR_HOME); $(MAKE)) + touch post.done + +clean.done: + rm -f post.done pre.done +endif diff --git a/com.oracle.truffle.r.native/library/lib.mk b/com.oracle.truffle.r.native/library/lib.mk index 727f096cb6a84cd50cc5e6250ce2aadc3e471375..4f6a44fcb9c53fa71a7161839d02d0fdc4e9cf31 100644 --- a/com.oracle.truffle.r.native/library/lib.mk +++ b/com.oracle.truffle.r.native/library/lib.mk @@ -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 @@ -103,9 +103,9 @@ $(GNUR_F_OBJECTS): | $(OBJ) $(OBJ): mkdir -p $(OBJ) -$(LIB_PKG): $(C_OBJECTS) $(F_OBJECTS) $(GNUR_C_OBJECTS) $(GNUR_F_OBJECTS) $(PKGDIR) +$(LIB_PKG): $(C_OBJECTS) $(F_OBJECTS) $(GNUR_C_OBJECTS) $(GNUR_F_OBJECTS) $(PKGDIR) $(XTRA_C_OBJECTS) mkdir -p $(LIBDIR) - $(DYLIB_LD) $(DYLIB_LDFLAGS) -o $(LIB_PKG) $(C_OBJECTS) $(F_OBJECTS) $(GNUR_C_OBJECTS) $(GNUR_F_OBJECTS) $(PKG_LIBS) + $(DYLIB_LD) $(DYLIB_LDFLAGS) -o $(LIB_PKG) $(C_OBJECTS) $(F_OBJECTS) $(GNUR_C_OBJECTS) $(GNUR_F_OBJECTS) $(XTRA_C_OBJECTS) $(PKG_LIBS) mkdir -p $(FASTR_LIBRARY_DIR)/$(PKG)/libs cp $(LIB_PKG) $(FASTR_LIBRARY_DIR)/$(PKG)/libs ifeq ($(OS_NAME),Darwin) diff --git a/com.oracle.truffle.r.native/library/tools/Makefile b/com.oracle.truffle.r.native/library/tools/Makefile index 3bf843f9574ecd0e8361ef017dc4911a156257de..f044af7d7ee2e27bf916d756996d9d80bf577cec 100644 --- a/com.oracle.truffle.r.native/library/tools/Makefile +++ b/com.oracle.truffle.r.native/library/tools/Makefile @@ -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 @@ -33,6 +33,21 @@ LIB_PKG_PRE = $(GRAMRD_OBJ) CLEAN_PKG = rm_gramRd +ifeq ($(FASTR_RFFI),nfi) +XTRA_C_SOURCES += $(SRC)/truffle_nfi/gramRd_nfi.c +XTRA_C_OBJECTS += $(OBJ)/gramRd_nfi.o +else +ifeq ($(FASTR_RFFI),llvm) +XTRA_C_SOURCES += $(SRC)/truffle_llvm/gramRd_llvm.c +XTRA_C_OBJECTS += $(OBJ)/gramRd_llvm.o +else +ifeq ($(FASTR_RFFI),jni) +XTRA_C_SOURCES += $(SRC)/jni/gramRd_jni.c +XTRA_C_OBJECTS += $(OBJ)/gramRd_jni.o +endif +endif +endif + include ../lib.mk # in case already generated @@ -46,5 +61,11 @@ $(SRC)/gramRd.c: $(GNUR_SRC)/gramRd.c $(OBJ)/%.o: $(GNUR_SRC)/%.c $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ +$(OBJ)/gramRd_nfi.o: $(SRC)/truffle_nfi/gramRd_nfi.c + $(CC) $(CFLAGS) $(FFI_INCLUDES) -c $< -o $@ + +$(OBJ)/gramRd_jni.o: $(SRC)/jni/gramRd_jni.c + $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + rm_gramRd: rm -f $(SRC)/gramRd.c diff --git a/com.oracle.truffle.r.native/library/tools/src/gramRd_jni.c b/com.oracle.truffle.r.native/library/tools/src/jni/gramRd_jni.c similarity index 94% rename from com.oracle.truffle.r.native/library/tools/src/gramRd_jni.c rename to com.oracle.truffle.r.native/library/tools/src/jni/gramRd_jni.c index c109bff1be15b1e26777045b48b43e0f87bc186f..14eb60c2e94a38f78acba3bf9e61fd706ace85b9 100644 --- a/com.oracle.truffle.r.native/library/tools/src/gramRd_jni.c +++ b/com.oracle.truffle.r.native/library/tools/src/jni/gramRd_jni.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -#include "gramRd_fastr.h" +#include "../gramRd_fastr.h" #include <jni.h> extern JNIEnv *getEnv(); diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ArgumentMapperSampler.java b/com.oracle.truffle.r.native/library/tools/src/truffle_nfi/gramRd_nfi.c similarity index 74% rename from com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ArgumentMapperSampler.java rename to com.oracle.truffle.r.native/library/tools/src/truffle_nfi/gramRd_nfi.c index 8b1b6b0197f07abae556f88304bbb0047db38715..c5716bb4c39a020499f69b2c1d97ecc4edb3d2a1 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ArgumentMapperSampler.java +++ b/com.oracle.truffle.r.native/library/tools/src/truffle_nfi/gramRd_nfi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,14 +20,14 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.nodes.casts; +#include "../gramRd_fastr.h" -import com.oracle.truffle.r.nodes.builtin.ArgumentMapper; +static int (*call_RConnGetC)(void *conn); -public interface ArgumentMapperSampler<T, R> extends ArgumentMapper<T, R> { - - TypeExpr resultTypes(TypeExpr inputTypes); - - Samples<T> collectSamples(Samples<R> downStreamSamples); +void gramRd_nfi_init(void *closure) { + call_RConnGetC = closure; +} +int callGetCMethod(void *conn) { + return call_RConnGetC(conn); } diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source index 78c24caea0d6432c6894a971ae42532768cc80d4..2bd5a0a98a36cc08ada88b804d3be047e6aa5b8a 100644 --- a/com.oracle.truffle.r.native/version.source +++ b/com.oracle.truffle.r.native/version.source @@ -1 +1 @@ -2/10/17 +22 diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/EagerResourceHandlerFactory.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/EagerResourceHandlerFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..701bc12f35e8be31b0a6024361e7558becdebd2e --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/EagerResourceHandlerFactory.java @@ -0,0 +1,156 @@ +/* + * 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.nodes.builtin; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.CodeSource; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.ResourceHandlerFactory; +import com.oracle.truffle.r.runtime.ResourceHandlerFactory.Handler; + +/** + * Implementation of {@link ResourceHandlerFactory} that pre-loads all the resources in its static + * constructor. + */ +public class EagerResourceHandlerFactory extends ResourceHandlerFactory implements Handler { + private static class FileInfo { + private final String name; + private final URL url; + private byte[] data; + + FileInfo(String name, URL url, byte[] data) { + this.name = name; + this.url = url; + this.data = data; + } + + @Override + public String toString() { + return "name: " + name + ", url: " + url.toString(); + } + } + + private static HashMap<String, FileInfo> files = new HashMap<>(); + + static { + gatherResources(); + } + + @Override + public URL getResource(Class<?> accessor, String name) { + return files.get(name).url; + } + + @Override + public InputStream getResourceAsStream(Class<?> accessor, String name) { + // actual resource + String fileName = Paths.get(name).getFileName().toString(); + FileInfo fileInfo = files.get(fileName); + if (fileInfo == null || fileInfo.data == null) { + RInternalError.shouldNotReachHere("getResourceAsStream: failed to find resource: " + name); + return null; + } else { + return new ByteArrayInputStream(fileInfo.data); + } + } + + @Override + protected Handler newHandler() { + return this; + } + + public static boolean addResource(@SuppressWarnings("unused") Class<?> accessor, String name, String path, boolean capture) { + byte[] bytes = null; + if (capture) { + try { + bytes = Files.readAllBytes(Paths.get(path)); + } catch (IOException ex) { + return false; + } + } + try { + files.put(name, new FileInfo(name, new URL("file://" + path), bytes)); + } catch (MalformedURLException ex) { + RInternalError.shouldNotReachHere("addResource " + ex.getMessage()); + } + return true; + } + + private static void gatherResources() { + CodeSource source = RBuiltinPackage.class.getProtectionDomain().getCodeSource(); + try { + URL jarURL = source.getLocation(); + JarFile fastrJar = new JarFile(new File(jarURL.toURI())); + Enumeration<JarEntry> iter = fastrJar.entries(); + while (iter.hasMoreElements()) { + JarEntry entry = iter.nextElement(); + String name = entry.getName(); + if (name.endsWith(".R") || name.endsWith("CONTRIBUTORS")) { + int size = (int) entry.getSize(); + byte[] buf = new byte[size]; + InputStream is = fastrJar.getInputStream(entry); + int totalRead = 0; + int n; + while ((n = is.read(buf, totalRead, buf.length - totalRead)) > 0) { + totalRead += n; + } + // using a proper jar URL causes build image problems + // and no-one really cares what the URL is - we have the data already + String fileName = Paths.get(name).getFileName().toString(); + files.put(fileName, new FileInfo(fileName, new URL("file://" + name), buf)); + } + } + } catch (Exception ex) { + RInternalError.shouldNotReachHere("error locating resources: " + ex.getMessage()); + } + } + + @Override + public String[] getRFiles(Class<?> accessor, String pkgName) { + ArrayList<String> list = new ArrayList<>(); + for (Map.Entry<String, FileInfo> entry : files.entrySet()) { + if (entry.getValue().url.toString().contains(pkgName + "/R")) { + String content = new String(entry.getValue().data); + list.add(content); + } + } + String[] result = new String[list.size()]; + list.toArray(result); + return result; + } + +} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java index 535045ab1cba59cf3f21c3d8f60549161d9a1f2c..aac98e96fe31cdff43ad564b9b6b09520fd8b701 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.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 @@ -31,10 +31,13 @@ import java.util.Map; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.RootCallTarget; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.r.nodes.builtin.base.BasePackage; import com.oracle.truffle.r.nodes.builtin.base.BaseVariables; +import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.REnvVars; import com.oracle.truffle.r.runtime.RInternalError; @@ -51,6 +54,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.env.REnvironment.PutException; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; /** * Support for loading the base package and also optional overrides for the packages provided with @@ -92,14 +96,16 @@ public final class RBuiltinPackages implements RBuiltinLookup { Path basePathbase = baseDirPath.resolve("R").resolve("base"); Source baseSource = null; try { - baseSource = RSource.fromFileName(basePathbase.toString()); + baseSource = RSource.fromFileName(basePathbase.toString(), true); } catch (IOException ex) { - Utils.rSuicide(String.format("unable to open the base package %s", basePathbase)); + throw Utils.rSuicide(String.format("unable to open the base package %s", basePathbase)); } // Load the (stub) DLL for base - String path = baseDirPath.resolve("libs").resolve("base.so").toString(); - Source loadSource = RSource.fromTextInternal(".Internal(dyn.load(" + RRuntime.quoteString(path, false) + ", TRUE, TRUE, \"\"))", RSource.Internal.R_IMPL); - RContext.getEngine().parseAndEval(loadSource, baseFrame, false); + if (FastROptions.LoadPackagesNativeCode.getBooleanValue()) { + String path = baseDirPath.resolve("libs").resolve("base.so").toString(); + Source loadSource = RSource.fromTextInternal(".Internal(dyn.load(" + RRuntime.escapeString(path, false, true) + ", TRUE, TRUE, \"\"))", RSource.Internal.R_IMPL); + RContext.getEngine().parseAndEval(loadSource, baseFrame, false); + } // Any RBuiltinKind.SUBSTITUTE functions installed above should not be overridden try { @@ -152,13 +158,22 @@ public final class RBuiltinPackages implements RBuiltinLookup { return createFunction(builtin, methodName); } + private static RootCallTarget createArgumentsCallTarget(RBuiltinFactory builtin) { + CompilerAsserts.neverPartOfCompilation(); + + FrameDescriptor frameDescriptor = new FrameDescriptor(); + RBuiltinRootNode root = new RBuiltinRootNode(builtin, frameDescriptor, null); + FrameSlotChangeMonitor.initializeFunctionFrameDescriptor(builtin.getName(), frameDescriptor); + return Truffle.getRuntime().createCallTarget(root); + } + private static RFunction createFunction(RBuiltinFactory builtinFactory, String methodName) { try { RFunction function = cachedBuiltinFunctions.get(methodName); if (function != null) { return function; } - RootCallTarget callTarget = RBuiltinNode.createArgumentsCallTarget(builtinFactory); + RootCallTarget callTarget = createArgumentsCallTarget(builtinFactory); function = RDataFactory.createFunction(builtinFactory.getName(), "base", callTarget, builtinFactory, null); cachedBuiltinFunctions.put(methodName, function); return function; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java index 40b36e8afd01bb2d92e74b6bda6dbeb65c326d36..5930d40906f9b27ab93507d436d496c1d7a2b457 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java @@ -41,9 +41,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; // TODO: add (permuted) dimnames to the result @RBuiltin(name = "aperm", kind = INTERNAL, parameterNames = {"a", "perm", "resize"}, behavior = PURE) -public abstract class APerm extends RBuiltinNode { +public abstract class APerm extends RBuiltinNode.Arg3 { - private final BranchProfile errorProfile = BranchProfile.create(); private final BranchProfile emptyPermVector = BranchProfile.create(); private final ConditionProfile mustResize = ConditionProfile.createBinaryProfile(); @@ -56,8 +55,7 @@ public abstract class APerm extends RBuiltinNode { private void checkErrorConditions(int[] dim) { if (!GetDimAttributeNode.isArray(dim)) { - errorProfile.enter(); - throw RError.error(RError.SHOW_CALLER, RError.Message.FIRST_ARG_MUST_BE_ARRAY); + throw error(RError.Message.FIRST_ARG_MUST_BE_ARRAY); } } @@ -137,8 +135,7 @@ public abstract class APerm extends RBuiltinNode { RList dimNames = getDimNamesNode.getDimNames(vector); if (dimNames == null) { // TODO: this error is reported after IS_OF_WRONG_LENGTH in GnuR - errorProfile.enter(); - throw RError.error(this, RError.Message.DOES_NOT_HAVE_DIMNAMES, "a"); + throw error(RError.Message.DOES_NOT_HAVE_DIMNAMES, "a"); } int[] perm = new int[permVector.getLength()]; @@ -176,22 +173,19 @@ public abstract class APerm extends RBuiltinNode { for (int i = 0; i < perm.getLength(); i++) { int pos = perm.getDataAt(i) - 1; // Adjust to zero based permute. if (pos >= perm.getLength() || pos < 0) { - errorProfile.enter(); - throw RError.error(RError.SHOW_CALLER, RError.Message.VALUE_OUT_OF_RANGE, "perm"); + throw error(RError.Message.VALUE_OUT_OF_RANGE, "perm"); } arrayPerm[i] = pos; if (visited[pos]) { // Duplicate dimension mapping in permute - errorProfile.enter(); - throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "perm"); + throw error(RError.Message.INVALID_ARGUMENT, "perm"); } visited[pos] = true; } return arrayPerm; } else { // perm size error - errorProfile.enter(); - throw RError.error(RError.SHOW_CALLER, RError.Message.IS_OF_WRONG_LENGTH, "perm", perm.getLength(), dim.length); + throw error(RError.Message.IS_OF_WRONG_LENGTH, "perm", perm.getLength(), dim.length); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abbrev.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abbrev.java index acf3a5b1ccef9d7419ebddf41ed5ae6539117822..d12d0d396185590281e40b70bf973a6dceaba3a9 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abbrev.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abbrev.java @@ -26,14 +26,14 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "abbreviate", kind = INTERNAL, parameterNames = {"x", "minlength", "use.classes"}, behavior = PURE) -public abstract class Abbrev extends RBuiltinNode { +public abstract class Abbrev extends RBuiltinNode.Arg3 { private final NACheck naCheck = NACheck.create(); static { Casts casts = new Casts(Abbrev.class); casts.arg("x").mustBe(stringValue()); - casts.arg("minlength").asIntegerVector().findFirst().notNA(); - casts.arg("use.classes").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("minlength").asIntegerVector().findFirst().mustNotBeNA(); + casts.arg("use.classes").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java index ce62baed1abe2db4b930fa56602958929a9556ab..7a73125009e2d2c99480dfcbc6ecb84440a15b55 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java @@ -49,13 +49,13 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor; @RBuiltin(name = "all.names", kind = INTERNAL, parameterNames = {"expr", "functions", "max.names", "unique"}, behavior = PURE) -public abstract class AllNames extends RBuiltinNode { +public abstract class AllNames extends RBuiltinNode.Arg4 { static { Casts casts = new Casts(AllNames.class); - casts.arg("functions").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).notNA(RRuntime.LOGICAL_FALSE); - casts.arg("max.names").asIntegerVector().findFirst(0).notNA(0); - casts.arg("unique").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).notNA(RRuntime.LOGICAL_TRUE); + casts.arg("functions").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).replaceNA(RRuntime.LOGICAL_FALSE); + casts.arg("max.names").asIntegerVector().findFirst(0).replaceNA(0); + casts.arg("unique").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).replaceNA(RRuntime.LOGICAL_TRUE); } @Specialization @@ -108,7 +108,10 @@ public abstract class AllNames extends RBuiltinNode { protected Void visit(RSyntaxCall element) { accept(element.getSyntaxLHS()); for (RSyntaxElement arg : element.getSyntaxArguments()) { - accept(arg); + // unmatched arguments may still be null + if (arg != null) { + accept(arg); + } } return null; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java index dc146c10aaf54a033654d50bf5e9e8102579ed36..217ee20c8ec7163c7f1103833eef89499cdbad60 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java @@ -37,6 +37,7 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RComplex; 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.RRaw; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; @@ -49,7 +50,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "anyNA", kind = PRIMITIVE, parameterNames = {"x", "recursive"}, dispatch = INTERNAL_GENERIC, behavior = PURE) -public abstract class AnyNA extends RBuiltinNode { +public abstract class AnyNA extends RBuiltinNode.Arg2 { private final NACheck naCheck = NACheck.create(); @@ -60,6 +61,11 @@ public abstract class AnyNA extends RBuiltinNode { casts.arg("recursive").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); } + @Override + public Object[] getDefaultParameterValues() { + return new Object[]{RMissing.instance, RRuntime.LOGICAL_FALSE}; + } + private static byte doScalar(boolean isNA) { return RRuntime.asLogical(isNA); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java index 3ea1d01a8f12b4d3a02e4b7a63d878b9f658d953..b2eddad3015480640b7f423eec79d4bf52e7b15e 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java @@ -55,7 +55,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; * */ @RBuiltin(name = "args", kind = INTERNAL, parameterNames = {"name"}, behavior = COMPLEX) -public abstract class Args extends RBuiltinNode { +public abstract class Args extends RBuiltinNode.Arg1 { @Child private GetFunctions.Get getNode; @Child private FrameFunctions.ParentFrame parentFrameNode; @@ -72,6 +72,9 @@ public abstract class Args extends RBuiltinNode { if (getNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getNode = insert(GetNodeGen.create()); + } + if (parentFrameNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); parentFrameNode = insert(ParentFrameNodeGen.create()); } return args((RFunction) getNode.execute(frame, funName.getDataAt(0), parentFrameNode.execute(frame, 1), RType.Function.getName(), true)); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java index 0e7f1daddea24b9076390b40a68317ed7e35f4dd..9c16badfdc78a238005ca72d08897fff1d0db1c7 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java @@ -63,7 +63,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; * TODO complete. This is sufficient for the b25 benchmark use. */ @RBuiltin(name = "array", kind = INTERNAL, parameterNames = {"data", "dim", "dimnames"}, behavior = PURE) -public abstract class Array extends RBuiltinNode { +public abstract class Array extends RBuiltinNode.Arg3 { @Child private UpdateDimNames updateDimNames; @@ -78,9 +78,9 @@ public abstract class Array extends RBuiltinNode { static { Casts casts = new Casts(Array.class); - casts.arg("data").defaultError(RError.SHOW_CALLER, RError.Message.MUST_BE_VECTOR_BUT_WAS, "data", typeName()).mustBe(abstractVectorValue()); - casts.arg("dim").defaultError(RError.SHOW_CALLER, RError.Message.CANNOT_BE_LENGTH, "dims", 0).mustNotBeNull().asIntegerVector().mustBe(notEmpty()); - casts.arg("dimnames").defaultError(RError.SHOW_CALLER, RError.Message.DIMNAMES_LIST).allowNull().mustBe(instanceOf(RList.class)); + casts.arg("data").defaultError(RError.Message.MUST_BE_VECTOR_BUT_WAS, "data", typeName()).mustBe(abstractVectorValue()); + casts.arg("dim").defaultError(RError.Message.CANNOT_BE_LENGTH, "dims", 0).mustNotBeNull().asIntegerVector().mustBe(notEmpty()); + casts.arg("dimnames").defaultError(RError.Message.DIMNAMES_LIST).allowNull().mustBe(instanceOf(RList.class)); } private int dimDataHelper(RAbstractIntVector dim, int[] dimData) { @@ -94,9 +94,9 @@ public abstract class Array extends RBuiltinNode { totalLength *= dimData[i]; } if (seenNegative == dim.getLength() && seenNegative != 0) { - throw RError.error(this, RError.Message.DIMS_CONTAIN_NEGATIVE_VALUES); + throw error(RError.Message.DIMS_CONTAIN_NEGATIVE_VALUES); } else if (seenNegative > 0) { - throw RError.error(this, RError.Message.NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED); + throw error(RError.Message.NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED); } return totalLength; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java index afc469496d2fef4b66feb7ab30da478b5faefde6..436d647e5b0272fb1e93448706808a897b05d80b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java @@ -47,7 +47,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "as.call", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) -public abstract class AsCall extends RBuiltinNode { +public abstract class AsCall extends RBuiltinNode.Arg1 { private final ConditionProfile nullNamesProfile = ConditionProfile.createBinaryProfile(); @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create(); @@ -68,6 +68,10 @@ public abstract class AsCall extends RBuiltinNode { return Call.makeCallSourceUnavailable(((RAbstractStringVector) x.getDataAt(0)).getDataAt(0), avn); } else if (x.getDataAt(0) instanceof RFunction) { return Call.makeCallSourceUnavailable((RFunction) x.getDataAt(0), avn); + } else if (x.getDataAt(0) instanceof Integer) { + return Call.makeCallSourceUnavailable((Integer) x.getDataAt(0), avn); + } else if (x.getDataAt(0) instanceof Double) { + return Call.makeCallSourceUnavailable((Double) x.getDataAt(0), avn); } else { throw RInternalError.unimplemented(); } @@ -113,6 +117,6 @@ public abstract class AsCall extends RBuiltinNode { @Fallback protected Object asCallFunction(@SuppressWarnings("unused") Object x) { - throw RError.error(this, RError.Message.GENERIC, "invalid argument list"); + throw error(RError.Message.GENERIC, "invalid argument list"); } } 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 0c000916060ff4187bd10ca3e9214b106621644f..f76be777345451de573b7888e29b873a5e3065d9 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 @@ -24,6 +24,9 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asStringVector; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyStringVector; import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -34,29 +37,24 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "as.character", kind = PRIMITIVE, parameterNames = {"x", "..."}, dispatch = INTERNAL_GENERIC, behavior = PURE) -public abstract class AsCharacter extends RBuiltinNode { +public abstract class AsCharacter extends RBuiltinNode.Arg2 { private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile(); static { Casts casts = new Casts(AsCharacter.class); - casts.arg("x").mapIf(instanceOf(RAbstractListVector.class).not(), asStringVector()); + casts.arg("x").returnIf(missingValue().or(nullValue()), emptyStringVector()).mapIf(instanceOf(RAbstractListVector.class).not(), asStringVector()); } @Specialization - protected RAbstractStringVector asCharacter(@SuppressWarnings("unused") RNull n) { - return RDataFactory.createEmptyStringVector(); - } - - @Specialization - protected RAbstractStringVector asCharacter(RAbstractStringVector v) { + protected RAbstractStringVector asCharacter(RAbstractStringVector v, @SuppressWarnings("unused") RArgsValuesAndNames dotdotdot) { if (noAttributes.profile(v.getAttributes() == null)) { return v; } else { @@ -65,7 +63,7 @@ public abstract class AsCharacter extends RBuiltinNode { } @Specialization - protected RStringVector asCharacter(RAbstractListVector list) { + protected RStringVector asCharacter(RAbstractListVector list, @SuppressWarnings("unused") RArgsValuesAndNames dotdotdot) { int len = list.getLength(); boolean complete = RDataFactory.COMPLETE_VECTOR; String[] data = new String[len]; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java index a3878fe3db264360b99a8e48baa21b95de4953c4..71ceeb062649979478af5f5e6b8a98084da95243 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java @@ -41,14 +41,15 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "asCharacterFactor", kind = INTERNAL, parameterNames = "x", behavior = PURE) -public abstract class AsCharacterFactor extends RBuiltinNode { - private final NACheck naCheck = NACheck.create(); +public abstract class AsCharacterFactor extends RBuiltinNode.Arg1 { private static final RStringVector CLASS_FACTOR_VEC = RDataFactory.createStringVectorFromScalar(RRuntime.CLASS_FACTOR); - @Child InheritsNode inheritsNode = InheritsNodeGen.create(); - @Child CastToVectorNode castToVectorNode = CastToVectorNode.create(); + @Child private InheritsNode inheritsNode = InheritsNodeGen.create(); + @Child private CastToVectorNode castToVectorNode = CastToVectorNode.create(); @Child private GetFixedAttributeNode getLevelsAttrNode = GetFixedAttributeNode.create(RRuntime.LEVELS_ATTR_KEY); + private final NACheck naCheck = NACheck.create(); + static { Casts.noCasts(AsCharacterFactor.class); } @@ -57,15 +58,15 @@ public abstract class AsCharacterFactor extends RBuiltinNode { protected RStringVector doAsCharacterFactor(Object x) { byte isFactor = (byte) inheritsNode.execute(x, CLASS_FACTOR_VEC, false); if (isFactor == RRuntime.LOGICAL_FALSE) { - throw RError.error(RError.SHOW_CALLER, RError.Message.COERCE_NON_FACTOR); + throw error(RError.Message.COERCE_NON_FACTOR); } RIntVector xVec = (RIntVector) x; int n = xVec.getLength(); String[] data = new String[n]; Object levsAttr = getLevelsAttrNode.execute(xVec); Object levs; - if (levsAttr == null || !((levs = castToVectorNode.execute(levsAttr)) instanceof RAbstractStringVector)) { - throw RError.error(RError.SHOW_CALLER, RError.Message.MALFORMED_FACTOR); + if (levsAttr == null || !((levs = castToVectorNode.doCast(levsAttr)) instanceof RAbstractStringVector)) { + throw error(RError.Message.MALFORMED_FACTOR); } RAbstractStringVector levsString = (RAbstractStringVector) levs; int nl = levsString.getLength(); @@ -77,7 +78,7 @@ public abstract class AsCharacterFactor extends RBuiltinNode { } else if (xi >= 1 && xi <= nl) { data[i] = levsString.getDataAt(xi - 1); } else { - throw RError.error(RError.SHOW_CALLER, RError.Message.MALFORMED_FACTOR); + throw error(RError.Message.MALFORMED_FACTOR); } } return RDataFactory.createStringVector(data, naCheck.neverSeenNA()); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsComplex.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsComplex.java index 468752482966f3f41627408ee460d278d019bf50..6ca5279ac6d762e68ca312433b6fd419f6c4b119 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsComplex.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsComplex.java @@ -22,6 +22,9 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyComplexVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -30,27 +33,21 @@ import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RDispatch; import com.oracle.truffle.r.runtime.builtins.RBuiltin; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; @RBuiltin(name = "as.complex", kind = PRIMITIVE, dispatch = RDispatch.INTERNAL_GENERIC, parameterNames = {"x", "..."}, behavior = PURE) -public abstract class AsComplex extends RBuiltinNode { +public abstract class AsComplex extends RBuiltinNode.Arg2 { private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile(); static { Casts casts = new Casts(AsComplex.class); - casts.arg("x").asComplexVector(); + casts.arg("x").returnIf(missingValue().or(nullValue()), emptyComplexVector()).asComplexVector(); } @Specialization - protected RAbstractComplexVector asComplex(@SuppressWarnings("unused") RNull n) { - return RDataFactory.createEmptyComplexVector(); - } - - @Specialization - protected RAbstractComplexVector asComplex(RAbstractComplexVector v) { + protected RAbstractComplexVector asComplex(RAbstractComplexVector v, @SuppressWarnings("unused") RArgsValuesAndNames dotdotdot) { if (noAttributes.profile(v.getAttributes() == null)) { return v; } else { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java index 7c65477dadaea01b5be7c7d03bf7f92fbad9f12d..fc78a3380061c29124b906e348e6805793462ca7 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java @@ -22,6 +22,9 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -29,27 +32,21 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.builtins.RBuiltin; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; @RBuiltin(name = "as.double", aliases = {"as.numeric"}, kind = PRIMITIVE, parameterNames = {"x", "..."}, behavior = PURE) -public abstract class AsDouble extends RBuiltinNode { +public abstract class AsDouble extends RBuiltinNode.Arg2 { private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile(); static { Casts casts = new Casts(AsDouble.class); - casts.arg("x").asDoubleVector(); + casts.arg("x").returnIf(missingValue().or(nullValue()), emptyDoubleVector()).asDoubleVector(); } @Specialization - protected RAbstractDoubleVector asDouble(@SuppressWarnings("unused") RNull n) { - return RDataFactory.createEmptyDoubleVector(); - } - - @Specialization - protected RAbstractDoubleVector asDouble(RAbstractDoubleVector v) { + protected RAbstractDoubleVector asDouble(RAbstractDoubleVector v, @SuppressWarnings("unused") RArgsValuesAndNames dotdotdot) { if (noAttributes.profile(v.getAttributes() == null)) { return v; } else { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java index a049ddd75dc54c4781821ef715b66ad4fc06e004..d465f8dea58e6a08ff9b0403d2e1274fc47eb3b7 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java @@ -45,6 +45,7 @@ import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RExpression; import com.oracle.truffle.r.runtime.data.RFunction; @@ -62,11 +63,11 @@ import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @RBuiltin(name = "as.function.default", kind = INTERNAL, parameterNames = {"x", "envir"}, behavior = PURE) -public abstract class AsFunction extends RBuiltinNode { +public abstract class AsFunction extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(AsFunction.class); - casts.arg("x").mustBe(instanceOf(RAbstractListVector.class).or(instanceOf(RExpression.class)), RError.SHOW_CALLER2, RError.Message.TYPE_EXPECTED, RType.List.getName()); + casts.arg("x").mustBe(instanceOf(RAbstractListVector.class).or(instanceOf(RExpression.class)), RError.Message.TYPE_EXPECTED, RType.List.getName()); casts.arg("envir").mustBe(instanceOf(REnvironment.class), RError.Message.INVALID_ENVIRONMENT); } @@ -74,7 +75,7 @@ public abstract class AsFunction extends RBuiltinNode { @TruffleBoundary protected RFunction asFunction(RAbstractVector x, REnvironment envir) { if (x.getLength() == 0) { - throw RError.error(this, RError.Message.GENERIC, "argument must have length at least 1"); + throw error(RError.Message.GENERIC, "argument must have length at least 1"); } SaveArgumentsNode saveArguments; FormalArguments formals; @@ -105,7 +106,7 @@ public abstract class AsFunction extends RBuiltinNode { } else { defaultValue = ReadVariableNode.create(symbol.getName()); } - } else if (RRuntime.asAbstractVector(arg) instanceof RAbstractVector) { + } else if (RRuntime.asAbstractVector(arg) instanceof RAttributable) { defaultValue = ConstantNode.create(arg); } else { throw RInternalError.unimplemented(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java index f7beffc392de4f77b2af3ee0d97f6649594bf5af..35f09fb010d3f10bd55af458dd42335abf4ed799 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java @@ -22,6 +22,9 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyIntegerVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -29,27 +32,21 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.builtins.RBuiltin; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @RBuiltin(name = "as.integer", kind = PRIMITIVE, parameterNames = {"x", "..."}, behavior = PURE) -public abstract class AsInteger extends RBuiltinNode { +public abstract class AsInteger extends RBuiltinNode.Arg2 { private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile(); static { Casts casts = new Casts(AsInteger.class); - casts.arg("x").asIntegerVector(); + casts.arg("x").returnIf(missingValue().or(nullValue()), emptyIntegerVector()).asIntegerVector(); } @Specialization - protected RAbstractIntVector asInteger(@SuppressWarnings("unused") RNull n) { - return RDataFactory.createEmptyIntVector(); - } - - @Specialization - protected RAbstractIntVector asInteger(RAbstractIntVector v) { + protected RAbstractIntVector asInteger(RAbstractIntVector v, @SuppressWarnings("unused") RArgsValuesAndNames dotdotdot) { if (noAttributes.profile(v.getAttributes() == null)) { return v; } else { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java index 5df1046a5c2b07131232094753f0ae1ba5b7792b..3bdca002dea69b0a8b6be9d467be2958010d683f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java @@ -22,6 +22,9 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyLogicalVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -29,27 +32,21 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.builtins.RBuiltin; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; @RBuiltin(name = "as.logical", kind = PRIMITIVE, parameterNames = {"x", "..."}, behavior = PURE) -public abstract class AsLogical extends RBuiltinNode { +public abstract class AsLogical extends RBuiltinNode.Arg2 { private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile(); static { Casts casts = new Casts(AsLogical.class); - casts.arg("x").asLogicalVector(); + casts.arg("x").returnIf(missingValue().or(nullValue()), emptyLogicalVector()).asLogicalVector(); } @Specialization - protected RAbstractLogicalVector asLogicaleger(@SuppressWarnings("unused") RNull n) { - return RDataFactory.createEmptyLogicalVector(); - } - - @Specialization - protected RAbstractLogicalVector asLogicaleger(RAbstractLogicalVector v) { + protected RAbstractLogicalVector asLogicaleger(RAbstractLogicalVector v, @SuppressWarnings("unused") RArgsValuesAndNames dotdotdot) { if (noAttributes.profile(v.getAttributes() == null)) { return v; } else { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java index cd935a7b146abb247afba1ce5a7ac40d0e740923..de58fbb3b766943aa47841bef6f4f71dea325ea8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java @@ -22,25 +22,27 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; @RBuiltin(name = "as.raw", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) -public abstract class AsRaw extends RBuiltinNode { +public abstract class AsRaw extends RBuiltinNode.Arg1 { private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile(); static { Casts casts = new Casts(AsRaw.class); - casts.arg("x").allowNull().asRawVector(); + casts.arg("x").mustBe(missingValue().not(), RError.Message.ARGUMENTS_PASSED, 0, "'as.raw'", 1).asRawVector(); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java index facf4b7d25493acf40217c6a9cf88bf2e047068a..ece6175263701856a21d98d2ceeb984d7dd58dc5 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java @@ -35,11 +35,11 @@ import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.AsVectorNodeGen.AsVectorInternalNodeGen; import com.oracle.truffle.r.nodes.builtin.base.AsVectorNodeGen.AsVectorInternalNodeGen.CastPairListNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.AsVectorNodeGen.AsVectorInternalNodeGen.DropAttributesNodeGen; import com.oracle.truffle.r.nodes.function.CallMatcherNode; import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen; @@ -61,18 +61,19 @@ import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.builtins.RBuiltin; -import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RExpression; import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector; import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; @RBuiltin(name = "as.vector", kind = INTERNAL, parameterNames = {"x", "mode"}, dispatch = INTERNAL_GENERIC, behavior = COMPLEX) -public abstract class AsVector extends RBuiltinNode { +public abstract class AsVector extends RBuiltinNode.Arg2 { @Child private AsVectorInternal internal = AsVectorInternalNodeGen.create(); @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false); @@ -96,7 +97,7 @@ public abstract class AsVector extends RBuiltinNode { @Specialization protected Object asVector(VirtualFrame frame, Object x, String mode) { // TODO given dispatch = INTERNAL_GENERIC, this should not be necessary - // However, removing it causes unit test failures + // However, INTERNAL_GENERIC is not handled for INTERNAL builtins RStringVector clazz = classHierarchy.execute(x); if (hasClassProfile.profile(clazz != null)) { // Note: this dispatch takes care of factor, because there is as.vector.factor @@ -121,43 +122,7 @@ public abstract class AsVector extends RBuiltinNode { public abstract Object execute(Object x, String mode); - private final ConditionProfile hasAttributes = ConditionProfile.createBinaryProfile(); private final ConditionProfile indirectMatchProfile = ConditionProfile.createBinaryProfile(); - private final BranchProfile vectorProfile = BranchProfile.create(); - private final ConditionProfile listProfile = ConditionProfile.createBinaryProfile(); - private final BranchProfile languageProfile = BranchProfile.create(); - private final BranchProfile symbolProfile = BranchProfile.create(); - private final BranchProfile expressionProfile = BranchProfile.create(); - - private Object dropAttributesIfNeeded(Object o) { - Object res = o; - if (res instanceof RAttributable && hasAttributes.profile(((RAttributable) res).getAttributes() != null)) { - // the assertion should hold because of how cast works and it's only used for - // vectors (as per as.vector docs) - if (res instanceof RExpression) { - expressionProfile.enter(); - return res; - } else if (res instanceof RAbstractVector) { - vectorProfile.enter(); - if (listProfile.profile(res instanceof RAbstractListVector)) { - // attributes are not dropped for list results - return res; - } else { - return ((RAbstractVector) res).copyDropAttributes(); - } - } else if (res instanceof RLanguage) { - languageProfile.enter(); - return RDataFactory.createLanguage(((RLanguage) res).getRep()); - } else if (res instanceof RSymbol) { - symbolProfile.enter(); - return RDataFactory.createSymbol(((RSymbol) res).getName()); - } else { - CompilerDirectives.transferToInterpreter(); - throw RInternalError.unimplemented("drop attributes for " + res.getClass().getSimpleName()); - } - } - return res; - } protected static CastNode createCast(RType type) { if (type != null) { @@ -201,8 +166,57 @@ public abstract class AsVector extends RBuiltinNode { protected Object asVector(Object x, String mode, @Cached("mode") String cachedMode, @Cached("fromMode(cachedMode)") RType type, - @Cached("createCast(type)") CastNode cast) { - return dropAttributesIfNeeded(cast == null ? x : cast.execute(x)); + @Cached("createCast(type)") CastNode cast, + @Cached("create()") DropAttributesNode drop) { + return drop.execute(cast == null ? x : cast.doCast(x)); + } + + public abstract static class DropAttributesNode extends RBaseNode { + + public abstract Object execute(Object o); + + public static DropAttributesNode create() { + return DropAttributesNodeGen.create(); + } + + protected static boolean hasAttributes(Class<? extends RAbstractAtomicVector> clazz, RAbstractAtomicVector o) { + return clazz.cast(o).getAttributes() != null; + } + + @Specialization(guards = "o.getAttributes() == null") + protected static RSharingAttributeStorage drop(RSharingAttributeStorage o) { + // quickly reject any RSharingAttributeStorage without attributes + return o; + } + + @Specialization(guards = "o.getClass() == oClass") + protected RAbstractVector dropCached(RAbstractAtomicVector o, + @Cached("o.getClass()") Class<? extends RAbstractAtomicVector> oClass, + @Cached("createBinaryProfile()") ConditionProfile profile) { + return profile.profile(hasAttributes(oClass, o)) ? oClass.cast(o).copyDropAttributes() : o; + } + + @Specialization(replaces = "dropCached") + protected RAbstractVector drop(RAbstractAtomicVector o, + @Cached("createBinaryProfile()") ConditionProfile profile) { + return profile.profile(o.getAttributes() != null) ? o.copyDropAttributes() : o; + } + + @Specialization(guards = "o.getAttributes() != null") + protected static RLanguage drop(RLanguage o) { + return RDataFactory.createLanguage(o.getRep()); + } + + @Specialization(guards = "o.getAttributes() != null") + protected static RSymbol drop(RSymbol o) { + return RDataFactory.createSymbol(o.getName()); + } + + @Fallback + protected Object drop(Object o) { + // includes RAbstractListVector, RExpression, RPairList + return o; + } } protected abstract static class CastPairListNode extends CastNode { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java index 9b191ab4b93b25fb0aafd0c06591117604ba9b67..316c04031c5cfebdcd71e84146bfc4551d2f11aa 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java @@ -30,8 +30,8 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.LoopNode; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.opt.ShareObjectNode; @@ -54,10 +54,8 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; * */ @RBuiltin(name = "assign", visibility = OFF, kind = INTERNAL, parameterNames = {"x", "value", "envir", "inherits"}, behavior = COMPLEX) -public abstract class Assign extends RBuiltinNode { +public abstract class Assign extends RBuiltinNode.Arg4 { - private final BranchProfile errorProfile = BranchProfile.create(); - private final BranchProfile warningProfile = BranchProfile.create(); private final boolean direct; protected Assign() { @@ -68,8 +66,11 @@ public abstract class Assign extends RBuiltinNode { this.direct = direct; } - private RBaseNode errorContext() { - return direct ? this : RError.SHOW_CALLER; + public abstract Object execute(VirtualFrame frame, RAbstractStringVector x, Object value, REnvironment pos, byte inherits); + + @Override + public RBaseNode getErrorContext() { + return direct ? this : super.getErrorContext(); } /** @@ -81,11 +82,9 @@ public abstract class Assign extends RBuiltinNode { if (len == 1) { return xVec.getDataAt(0); } else if (len == 0) { - errorProfile.enter(); - throw RError.error(errorContext(), RError.Message.INVALID_FIRST_ARGUMENT); + throw error(RError.Message.INVALID_FIRST_ARGUMENT); } else { - warningProfile.enter(); - RError.warning(errorContext(), RError.Message.ONLY_FIRST_VARIABLE_NAME); + warning(RError.Message.ONLY_FIRST_VARIABLE_NAME); return xVec.getDataAt(0); } } @@ -98,7 +97,7 @@ public abstract class Assign extends RBuiltinNode { // this argument could be made Boolean unless there were AssignFastPath relying upon the // byte argument - casts.arg("inherits").asLogicalVector().findFirst().notNA(); + casts.arg("inherits").asLogicalVector().findFirst().mustNotBeNA(); } /** @@ -125,15 +124,13 @@ public abstract class Assign extends RBuiltinNode { LoopNode.reportLoopCount(this, -1); } if (env == REnvironment.emptyEnv()) { - errorProfile.enter(); - throw RError.error(errorContext(), RError.Message.CANNOT_ASSIGN_IN_EMPTY_ENV); + throw error(RError.Message.CANNOT_ASSIGN_IN_EMPTY_ENV); } } try { env.put(x, share.execute(value)); } catch (PutException ex) { - errorProfile.enter(); - throw RError.error(errorContext(), ex); + throw error(ex); } return value; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AttachFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AttachFunctions.java index f1ef8beb37181a987574a97dd3a33f1608e1349f..82defa7b426037b985a828ad73ca535c01e57da3 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AttachFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AttachFunctions.java @@ -46,7 +46,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment.DetachException; public class AttachFunctions { @RBuiltin(name = "attach", visibility = OFF, kind = INTERNAL, parameterNames = {"what", "pos", "name"}, behavior = COMPLEX) - public abstract static class Attach extends RBuiltinNode { + public abstract static class Attach extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(Attach.class); @@ -103,7 +103,7 @@ public class AttachFunctions { } @RBuiltin(name = "detach", visibility = OFF, kind = INTERNAL, parameterNames = {"pos"}, behavior = COMPLEX) - public abstract static class Detach extends RBuiltinNode { + public abstract static class Detach extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(Detach.class); @@ -116,7 +116,7 @@ public class AttachFunctions { try { return REnvironment.detach(pos.getDataAt(0)); } catch (DetachException ex) { - throw RError.error(this, ex); + throw error(ex); } } } 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 530f77eb8e85431d5f057eaf5ae85b75bcdbdd36..e746de2a76368f54daa0461ad94e6659a1f0cfd7 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 @@ -33,7 +33,6 @@ 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.object.DynamicObject; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.attributes.GetAttributeNode; import com.oracle.truffle.r.nodes.attributes.IterableAttributeNode; @@ -49,18 +48,15 @@ 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.RInteger; 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; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "attr", kind = PRIMITIVE, parameterNames = {"x", "which", "exact"}, behavior = PURE) -public abstract class Attr extends RBuiltinNode { +public abstract class Attr extends RBuiltinNode.Arg3 { private final ConditionProfile searchPartialProfile = ConditionProfile.createBinaryProfile(); - private final BranchProfile errorProfile = BranchProfile.create(); @Child private UpdateShareableChildValueNode sharedAttrUpdate = UpdateShareableChildValueNode.create(); @Child private InternStringNode intern = InternStringNodeGen.create(); @@ -141,7 +137,6 @@ public abstract class Attr extends RBuiltinNode { if (object instanceof RAttributable) { return attrRA((RAttributable) object, intern.execute((String) name), (boolean) exact); } else { - errorProfile.enter(); throw RError.nyi(this, "object cannot be attributed"); } } @@ -150,9 +145,13 @@ public abstract class Attr extends RBuiltinNode { if (a == RNull.instance) { return RNull.instance; } else { - RAbstractVector rowNames = (RAbstractVector) a; - return rowNames.getElementClass() == RInteger.class && rowNames.getLength() == 2 && RRuntime.isNA(((RAbstractIntVector) rowNames).getDataAt(0)) ? RDataFactory.createIntSequence(1, 1, - Math.abs(((RAbstractIntVector) rowNames).getDataAt(1))) : a; + if (a instanceof RAbstractIntVector) { + RAbstractIntVector rowNames = (RAbstractIntVector) a; + if (rowNames.getLength() == 2 && RRuntime.isNA(rowNames.getDataAt(0))) { + return RDataFactory.createIntSequence(1, 1, Math.abs(rowNames.getDataAt(1))); + } + } + return a; } } 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 3c751dc9906fae8a7383ce2d6b64fc22af414917..c2e894809ced2e2442a1f0f9cb861a4604d390d7 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 @@ -50,7 +50,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.env.REnvironment; @RBuiltin(name = "attributes", kind = PRIMITIVE, parameterNames = {"obj"}, behavior = PURE) -public abstract class Attributes extends RBuiltinNode { +public abstract class Attributes extends RBuiltinNode.Arg1 { private final BranchProfile rownamesBranch = BranchProfile.create(); @Child private ArrayAttributeNode arrayAttrAccess = ArrayAttributeNode.create(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java index 005d49ee57fc65f2b4570d33060f89c9bb0bca5f..4ee6d5194ce3f1c778d4daae7f8153523bb28902 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java @@ -27,130 +27,110 @@ import static com.oracle.truffle.r.runtime.nmath.RMath.fmax2; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.BaseGammaFunctionsFactory.DpsiFnCalcNodeGen; import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDoubleVector; -import com.oracle.truffle.r.runtime.data.closures.RClosures; 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.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.nmath.GammaFunctions; import com.oracle.truffle.r.runtime.nmath.RMath; import com.oracle.truffle.r.runtime.ops.na.NACheck; public class BaseGammaFunctions { - @RBuiltin(name = "gamma", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) - public abstract static class Gamma extends RBuiltinNode { - @Specialization - @TruffleBoundary - protected RDoubleVector lgamma(@SuppressWarnings("unused") RAbstractDoubleVector x) { - throw RError.nyi(this, "gamma"); - } - } - - @RBuiltin(name = "trigamma", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) - public abstract static class TriGamma extends RBuiltinNode { - @Specialization - @TruffleBoundary - protected RDoubleVector trigamma(@SuppressWarnings("unused") RAbstractDoubleVector x) { - throw RError.nyi(this, "trigamma"); - } - } - - @RBuiltin(name = "lgamma", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) - public abstract static class Lgamma extends RBuiltinNode { + public abstract static class GammaBase extends RBuiltinNode.Arg1 { private final NACheck naValCheck = NACheck.create(); - static { - Casts casts = new Casts(Lgamma.class); + protected static void casts(Casts casts) { casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue()).asDoubleVector(); } @Specialization - protected RDoubleVector lgamma(RAbstractDoubleVector x) { - naValCheck.enable(true); + protected RDoubleVector digamma(RAbstractDoubleVector x) { + naValCheck.enable(x); double[] result = new double[x.getLength()]; + boolean warnNaN = false; for (int i = 0; i < x.getLength(); i++) { double xv = x.getDataAt(i); - result[i] = GammaFunctions.lgammafn(xv); - naValCheck.check(result[i]); + double val; + if (naValCheck.check(xv)) { + val = RRuntime.DOUBLE_NA; + } else { + val = scalarFunction(xv); + if (Double.isNaN(val)) { + warnNaN = true; + } + } + result[i] = val; + } + if (warnNaN) { + warning(RError.Message.NAN_PRODUCED); } return RDataFactory.createDoubleVector(result, naValCheck.neverSeenNA()); } - @Specialization - protected RDoubleVector lgamma(RAbstractIntVector x) { - return lgamma(RClosures.createIntToDoubleVector(x)); - } - - @Specialization - protected RDoubleVector lgamma(RAbstractLogicalVector x) { - return lgamma(RClosures.createLogicalToDoubleVector(x)); + protected double scalarFunction(@SuppressWarnings("unused") double xv) { + throw RInternalError.shouldNotReachHere(); } } - @RBuiltin(name = "digamma", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) - public abstract static class DiGamma extends RBuiltinNode { + @RBuiltin(name = "gamma", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) + public abstract static class Gamma extends GammaBase { - @Child private DpsiFnCalc dpsiFnCalc; + static { + casts(new Casts(Gamma.class)); + } - private final NACheck naValCheck = NACheck.create(); + @Override + protected double scalarFunction(double xv) { + return GammaFunctions.gammafn(xv); + } + } - private double dpsiFnCalc(double x, int n, int kode, double ans) { - if (dpsiFnCalc == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - dpsiFnCalc = insert(DpsiFnCalcNodeGen.create()); - } - return dpsiFnCalc.executeDouble(x, n, kode, ans); + @RBuiltin(name = "trigamma", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) + public abstract static class TriGamma extends GammaBase { + static { + casts(new Casts(TriGamma.class)); } + @Override + protected double scalarFunction(double xv) { + throw RError.nyi(this, "trigamma"); + } + } + + @RBuiltin(name = "lgamma", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) + public abstract static class Lgamma extends GammaBase { + static { - Casts casts = new Casts(DiGamma.class); - casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue()).asDoubleVector(); + casts(new Casts(Lgamma.class)); } - @Specialization - protected RDoubleVector digamma(RAbstractDoubleVector x) { - naValCheck.enable(x); - double[] result = new double[x.getLength()]; - boolean warnNaN = false; - for (int i = 0; i < x.getLength(); i++) { - double xv = x.getDataAt(i); - if (naValCheck.check(xv)) { - result[i] = xv; - } else { - double val = dpsiFnCalc(xv, 0, 1, 0); - if (Double.isNaN(val)) { - result[i] = val; - warnNaN = true; - } else { - result[i] = -val; - } - } - } - if (warnNaN) { - RError.warning(this, RError.Message.NAN_PRODUCED); - } - return RDataFactory.createDoubleVector(result, naValCheck.neverSeenNA()); + @Override + protected double scalarFunction(double xv) { + return GammaFunctions.lgammafn(xv); } + } - @Specialization - protected RDoubleVector digamma(RAbstractIntVector x) { - return digamma(RClosures.createIntToDoubleVector(x)); + @RBuiltin(name = "digamma", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) + public abstract static class DiGamma extends GammaBase { + + @Child private DpsiFnCalc dpsiFnCalc = DpsiFnCalcNodeGen.create(); + + static { + casts(new Casts(DiGamma.class)); } - @Specialization - protected RDoubleVector digamma(RAbstractLogicalVector x) { - return digamma(RClosures.createLogicalToDoubleVector(x)); + @Override + protected double scalarFunction(double xv) { + return -dpsiFnCalc.executeDouble(xv, 0, 1, 0); } } 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 fb195606ae5a5ebe010f5098fa1dde10f4d70572..c30232bc10d3b97eb4bb95c78daf7a29c4dfcc8e 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 @@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.builtin.base; import java.util.function.Supplier; import com.oracle.truffle.api.frame.MaterializedFrame; +import com.oracle.truffle.r.library.fastrGrid.DoSetViewPortBuiltin; import com.oracle.truffle.r.nodes.RRootNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.binary.BinaryArithmeticNodeGen; @@ -99,6 +100,8 @@ import com.oracle.truffle.r.nodes.builtin.fastr.FastRPkgSource; import com.oracle.truffle.r.nodes.builtin.fastr.FastRPkgSourceNodeGen; 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.FastRStackTrace; import com.oracle.truffle.r.nodes.builtin.fastr.FastRStackTraceNodeGen; import com.oracle.truffle.r.nodes.builtin.fastr.FastRStats.FastRProfAttr; @@ -230,7 +233,7 @@ public class BasePackage extends RBuiltinPackage { add(Ceiling.class, CeilingNodeGen::create); add(CharMatch.class, CharMatchNodeGen::create); add(Col.class, ColNodeGen::create); - add(Colon.class, ColonNodeGen::create); + add(Colon.class, ColonNodeGen::create, Colon::special); add(ColMeans.class, ColMeansNodeGen::create); add(ColSums.class, ColSumsNodeGen::create); add(Combine.class, CombineNodeGen::create); @@ -268,7 +271,13 @@ public class BasePackage extends RBuiltinPackage { add(ConnectionFunctions.ReadChar.class, ConnectionFunctionsFactory.ReadCharNodeGen::create); add(ConnectionFunctions.ReadLines.class, ConnectionFunctionsFactory.ReadLinesNodeGen::create); add(ConnectionFunctions.Seek.class, ConnectionFunctionsFactory.SeekNodeGen::create); + add(ConnectionFunctions.Truncate.class, ConnectionFunctionsFactory.TruncateNodeGen::create); add(ConnectionFunctions.SocketConnection.class, ConnectionFunctionsFactory.SocketConnectionNodeGen::create); + add(ConnectionFunctions.RawConnection.class, ConnectionFunctionsFactory.RawConnectionNodeGen::create); + add(ConnectionFunctions.RawConnectionValue.class, ConnectionFunctionsFactory.RawConnectionValueNodeGen::create); + add(ConnectionFunctions.ChannelConnection.class, ConnectionFunctionsFactory.ChannelConnectionNodeGen::create); + add(ConnectionFunctions.Fifo.class, ConnectionFunctionsFactory.FifoNodeGen::create); + add(ConnectionFunctions.Pipe.class, ConnectionFunctionsFactory.PipeNodeGen::create); add(ConnectionFunctions.Stderr.class, ConnectionFunctionsFactory.StderrNodeGen::create); add(ConnectionFunctions.Stdin.class, ConnectionFunctionsFactory.StdinNodeGen::create); add(ConnectionFunctions.Stdout.class, ConnectionFunctionsFactory.StdoutNodeGen::create); @@ -279,6 +288,7 @@ public class BasePackage extends RBuiltinPackage { add(ConnectionFunctions.WriteBin.class, ConnectionFunctionsFactory.WriteBinNodeGen::create); add(ConnectionFunctions.WriteChar.class, ConnectionFunctionsFactory.WriteCharNodeGen::create); add(ConnectionFunctions.WriteLines.class, ConnectionFunctionsFactory.WriteLinesNodeGen::create); + add(ConnectionFunctions.IsIncomplete.class, ConnectionFunctionsFactory.IsIncompleteNodeGen::create); add(Contributors.class, ContributorsNodeGen::create); add(CopyDFAttr.class, CopyDFAttrNodeGen::create); add(Crossprod.class, CrossprodNodeGen::create); @@ -365,15 +375,27 @@ public class BasePackage extends RBuiltinPackage { add(FastRInterop.Export.class, FastRInteropFactory.ExportNodeGen::create); add(FastRInterop.HasSize.class, FastRInteropFactory.HasSizeNodeGen::create); add(FastRInterop.Import.class, FastRInteropFactory.ImportNodeGen::create); + add(FastRInterop.InteropNew.class, FastRInteropFactory.InteropNewNodeGen::create); add(FastRInterop.IsNull.class, FastRInteropFactory.IsNullNodeGen::create); add(FastRInterop.IsExecutable.class, FastRInteropFactory.IsExecutableNodeGen::create); + add(FastRInterop.JavaClass.class, FastRInteropFactory.JavaClassNodeGen::create); + add(FastRInterop.IsJavaArray.class, FastRInteropFactory.IsJavaArrayNodeGen::create); + add(FastRInterop.NewJavaArray.class, FastRInteropFactory.NewJavaArrayNodeGen::create); + add(FastRInterop.ToJavaArray.class, FastRInteropFactory.ToJavaArrayNodeGen::create); + add(FastRInterop.FromJavaArray.class, FastRInteropFactory.FromJavaArrayNodeGen::create); add(FastRInterop.ToBoolean.class, FastRInteropFactory.ToBooleanNodeGen::create); + add(FastRInterop.ToByte.class, FastRInteropFactory.ToByteNodeGen::create); + add(FastRInterop.ToChar.class, FastRInteropFactory.ToCharNodeGen::create); + add(FastRInterop.ToFloat.class, FastRInteropFactory.ToFloatNodeGen::create); + add(FastRInterop.ToLong.class, FastRInteropFactory.ToLongNodeGen::create); + add(FastRInterop.ToShort.class, FastRInteropFactory.ToShortNodeGen::create); add(FastRRefCountInfo.class, FastRRefCountInfoNodeGen::create); add(FastRPkgSource.class, FastRPkgSourceNodeGen::create); add(FastRStackTrace.class, FastRStackTraceNodeGen::create); add(FastRProfAttr.class, FastRStatsFactory.FastRProfAttrNodeGen::create); add(FastRProfTypecounts.class, FastRStatsFactory.FastRProfTypecountsNodeGen::create); add(FastRProfFuncounts.class, FastRStatsFactory.FastRProfFuncountsNodeGen::create); + add(FastRSlotAssign.class, FastRSlotAssignNodeGen::create); add(FastRSyntaxTree.class, FastRSyntaxTreeNodeGen::create); add(FastRThrowIt.class, FastRThrowItNodeGen::create); add(FastRTrace.Trace.class, FastRTraceFactory.TraceNodeGen::create); @@ -431,7 +453,8 @@ public class BasePackage extends RBuiltinPackage { add(GrepFunctions.Gregexpr.class, GrepFunctionsFactory.GregexprNodeGen::create); add(GrepFunctions.Grep.class, GrepFunctionsFactory.GrepNodeGen::create); add(GrepFunctions.GrepL.class, GrepFunctionsFactory.GrepLNodeGen::create); - add(GrepFunctions.Regexp.class, GrepFunctionsFactory.RegexpNodeGen::create); + add(GrepFunctions.Regexpr.class, GrepFunctionsFactory.RegexprNodeGen::create); + add(GrepFunctions.Regexec.class, GrepFunctionsFactory.RegexecNodeGen::create); add(GrepFunctions.Strsplit.class, GrepFunctionsFactory.StrsplitNodeGen::create); add(GrepFunctions.Sub.class, GrepFunctionsFactory.SubNodeGen::create); add(HiddenInternalFunctions.GetRegisteredRoutines.class, HiddenInternalFunctionsFactory.GetRegisteredRoutinesNodeGen::create); @@ -482,6 +505,7 @@ public class BasePackage extends RBuiltinPackage { add(IsUnsorted.class, IsUnsortedNodeGen::create); add(LaFunctions.DetGeReal.class, LaFunctionsFactory.DetGeRealNodeGen::create); add(LaFunctions.LaChol.class, LaFunctionsFactory.LaCholNodeGen::create); + add(LaFunctions.LaChol2Inv.class, LaFunctionsFactory.LaChol2InvNodeGen::create); add(LaFunctions.Qr.class, LaFunctionsFactory.QrNodeGen::create); add(LaFunctions.QrCoefReal.class, LaFunctionsFactory.QrCoefRealNodeGen::create); add(LaFunctions.Rg.class, LaFunctionsFactory.RgNodeGen::create); @@ -715,6 +739,13 @@ public class BasePackage extends RBuiltinPackage { add(UpdateSubset.class, UpdateSubsetNodeGen::create, UpdateSubset::special); add(UpdateField.class, UpdateFieldNodeGen::create, UpdateField::createSpecial); add(WhileBuiltin.class, WhileBuiltinNodeGen::create); + + // grid intrinsics + addGridIntrinsics(); + } + + private void addGridIntrinsics() { + add(DoSetViewPortBuiltin.class, DoSetViewPortBuiltin::create); } private void addBinaryArithmetic(Class<?> builtinClass, BinaryArithmeticFactory binaryFactory, UnaryArithmeticFactory unaryFactory) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java index 1c9c02253cef6f4fe4698f6ebc41ffec753b712b..332f4021fd4468981591d6235d62bd2d1d8ee474 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java @@ -16,33 +16,50 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "bincode", kind = INTERNAL, parameterNames = {"x", "breaks", "right", "include.lowest"}, behavior = PURE) -public abstract class Bincode extends RBuiltinNode { +public abstract class Bincode extends RBuiltinNode.Arg4 { - private final BranchProfile errorProfile = BranchProfile.create(); private final NACheck naCheck = NACheck.create(); static { Casts casts = new Casts(Bincode.class); - casts.arg("x").asDoubleVector(); + casts.arg("x").mustNotBeMissing(RError.Message.ARGUMENT_EMPTY, 1).asDoubleVector(); - casts.arg("breaks").asDoubleVector(); + casts.arg("breaks").mustNotBeMissing(RError.Message.ARGUMENT_EMPTY, 2).asDoubleVector(); casts.arg("right").asLogicalVector().findFirst().map(toBoolean()); casts.arg("include.lowest").asLogicalVector().findFirst().map(toBoolean()); } + @SuppressWarnings("unused") + @Specialization + RIntVector formatC(RNull x, RAbstractDoubleVector breaks, boolean right, boolean includeBorder) { + return RDataFactory.createEmptyIntVector(); + } + + @SuppressWarnings("unused") + @Specialization + RIntVector formatC(RNull x, RNull breaks, boolean right, boolean includeBorder) { + return RDataFactory.createEmptyIntVector(); + } + + @SuppressWarnings("unused") + @Specialization + RIntVector formatC(RAbstractDoubleVector x, RNull breaks, boolean right, boolean includeBorder) { + return RDataFactory.createIntVector(x.getLength(), true); + } + @Specialization RIntVector formatC(RAbstractDoubleVector x, RAbstractDoubleVector breaks, boolean right, boolean includeBorder) { int n = x.getLength(); @@ -58,8 +75,7 @@ public abstract class Bincode extends RBuiltinNode { /* This relies on breaks being sorted, so wise to check that */ for (int i = 1; i < nb; i++) { if (breaks.getDataAt(i - 1) > breaks.getDataAt(i)) { - errorProfile.enter(); - throw RError.error(this, RError.Message.GENERIC, "'breaks' is not sorted"); + throw error(RError.Message.GENERIC, "'breaks' is not sorted"); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java index 14584bfb602fe33c6aaf0ebe0e2016955e4e92c9..1247be422fe02181dc6da7960e969f6674ed44f2 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java @@ -111,6 +111,7 @@ public abstract class Bind extends RBaseNode { private final ConditionProfile emptyVectorProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile allEmptyVectorProfile = ConditionProfile.createBinaryProfile(); private final BranchProfile nonNullNames = BranchProfile.create(); + private final ConditionProfile dimNamesInComplete = ConditionProfile.createBinaryProfile(); private final NACheck naCheck = NACheck.create(); protected final ValueProfile resultProfile = ValueProfile.createClassProfile(); protected final ValueProfile vectorProfile = ValueProfile.createClassProfile(); @@ -132,7 +133,7 @@ public abstract class Bind extends RBaseNode { CompilerDirectives.transferToInterpreterAndInvalidate(); castVector = insert(CastToVectorNodeGen.create(false)); } - return (RAbstractVector) castVector.execute(value); + return (RAbstractVector) castVector.doCast(value); } protected Object castLogical(Object operand, boolean preserveAllAttr) { @@ -140,7 +141,7 @@ public abstract class Bind extends RBaseNode { CompilerDirectives.transferToInterpreterAndInvalidate(); castLogical = insert(CastLogicalNodeGen.create(true, preserveAllAttr, preserveAllAttr)); } - return castLogical.execute(operand); + return castLogical.doCast(operand); } @SuppressWarnings("unused") @@ -194,22 +195,22 @@ public abstract class Bind extends RBaseNode { boolean rowsAndColumnsNotEqual = getResultDimensions(vectors, resultDimensions, bindDims); RVector<?> resultVec; if (fromNotNullArgVector != null) { - resultVec = resultProfile.profile(fromNotNullArgVector.createEmptySameType(resultDimensions[0] * resultDimensions[1], complete)); + resultVec = resultProfile.profile(vectorProfile.profile(fromNotNullArgVector).createEmptySameType(resultDimensions[0] * resultDimensions[1], complete)); } else { - resultVec = resultProfile.profile(vectors[0].createEmptySameType(resultDimensions[0] * resultDimensions[1], complete)); + resultVec = resultProfile.profile(vectorProfile.profile(vectors[0]).createEmptySameType(resultDimensions[0] * resultDimensions[1], complete)); } if (type == BindType.cbind) { - return genericCBind(promiseArgs, vectors, resultVec, resultDimensions, bindDims, rowsAndColumnsNotEqual, allEmpty, vecNames, naCheck.neverSeenNA(), deparseLevel, setDimNode, - getDimNamesNode, getNamesNode); + return genericCBind(promiseArgs, vectors, resultVec, resultDimensions, bindDims, rowsAndColumnsNotEqual, allEmpty, vecNames, deparseLevel, setDimNode, getDimNamesNode, + getNamesNode); } else { - return genericRBind(promiseArgs, vectors, resultVec, resultDimensions, bindDims, rowsAndColumnsNotEqual, allEmpty, vecNames, naCheck.neverSeenNA(), deparseLevel, setDimNode, - getDimNamesNode, getNamesNode); + return genericRBind(promiseArgs, vectors, resultVec, resultDimensions, bindDims, rowsAndColumnsNotEqual, allEmpty, vecNames, deparseLevel, setDimNode, getDimNamesNode, + getNamesNode); } } private RAbstractVector getVector(Object arg, CastNode castNode, boolean needsVectorCast) { - Object result = castNode.execute(arg); + Object result = castNode.doCast(arg); RAbstractVector vector; if (needsVectorCast) { vector = castVector(result); @@ -472,8 +473,8 @@ public abstract class Bind extends RBaseNode { } public RVector<?> genericCBind(RArgsValuesAndNames promiseArgs, RAbstractVector[] vectors, RVector<?> result, int[] resultDimensions, int[] secondDims, boolean rowsAndColumnsNotEqual, - boolean allEmpty, String[] vecNames, boolean vecNamesComplete, int deparseLevel, - SetDimAttributeNode setDimNode, GetDimNamesAttributeNode getDimNamesNode, GetNamesAttributeNode getNamesNode) { + boolean allEmpty, String[] vecNames, int deparseLevel, SetDimAttributeNode setDimNode, + GetDimNamesAttributeNode getDimNamesNode, GetNamesAttributeNode getNamesNode) { int ind = 0; Object rowDimResultNames = RNull.instance; @@ -516,7 +517,7 @@ public abstract class Bind extends RBaseNode { } } } - Object colDimResultNames = allColDimNamesNull ? RNull.instance : RDataFactory.createStringVector(colDimNamesArray, vecNamesComplete); + Object colDimResultNames = allColDimNamesNull ? RNull.instance : RDataFactory.createStringVector(colDimNamesArray, dimResultNamesComplete(colDimNamesArray)); setDimNode.setDimensions(result, resultDimensions); if (needsDimNames.profile(allEmpty || rowDimResultNames != RNull.instance || colDimResultNames != RNull.instance)) { setDimNames(result, RDataFactory.createList(new Object[]{rowDimResultNames, colDimResultNames})); @@ -546,7 +547,7 @@ public abstract class Bind extends RBaseNode { } } - protected abstract static class AbstractBind extends RBuiltinNode { + protected abstract static class AbstractBind extends RBuiltinNode.Arg2 { @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false); private final ConditionProfile hasClassProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile hasDispatchFunction = ConditionProfile.createBinaryProfile(); @@ -584,7 +585,12 @@ public abstract class Bind extends RBaseNode { CompilerDirectives.transferToInterpreterAndInvalidate(); bind = insert(BindNodeGen.create(type)); } - return bind.execute(frame, deparseLevel, args.getArguments(), (RArgsValuesAndNames) RArguments.getArgument(frame, 0), precedence(args.getArguments())); + Object firstArg = RArguments.getArgument(frame, 0); + RArgsValuesAndNames promisedArgs = args; + if (firstArg instanceof RArgsValuesAndNames) { + promisedArgs = (RArgsValuesAndNames) firstArg; + } + return bind.execute(frame, deparseLevel, args.getArguments(), promisedArgs, precedence(args.getArguments())); } } @@ -608,6 +614,9 @@ public abstract class Bind extends RBaseNode { if (lookup == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); lookup = insert(S3FunctionLookupNode.create(false, false)); + } + if (getBaseEnv == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); getBaseEnv = insert(GetBaseEnvFrameNode.create()); } Result r = lookup.execute(frame, type.toString(), clazz, null, frame.materialize(), getBaseEnv.execute()); @@ -626,8 +635,8 @@ public abstract class Bind extends RBaseNode { } public RVector<?> genericRBind(RArgsValuesAndNames promiseArgs, RAbstractVector[] vectors, RVector<?> result, int[] resultDimensions, int[] firstDims, boolean rowsAndColumnsNotEqual, - boolean allEmpty, String[] vecNames, boolean vecNamesComplete, int deparseLevel, - SetDimAttributeNode setDimNode, GetDimNamesAttributeNode getDimNamesNode, GetNamesAttributeNode getNamesNode) { + boolean allEmpty, String[] vecNames, int deparseLevel, SetDimAttributeNode setDimNode, + GetDimNamesAttributeNode getDimNamesNode, GetNamesAttributeNode getNamesNode) { Object colDimResultNames = RNull.instance; String[] rowDimNamesArray = new String[resultDimensions[0]]; @@ -676,7 +685,7 @@ public abstract class Bind extends RBaseNode { dstRowInd += firstDims[i]; } - Object rowDimResultNames = allRowDimNamesNull ? RNull.instance : RDataFactory.createStringVector(rowDimNamesArray, vecNamesComplete); + Object rowDimResultNames = allRowDimNamesNull ? RNull.instance : RDataFactory.createStringVector(rowDimNamesArray, dimResultNamesComplete(rowDimNamesArray)); setDimNode.setDimensions(result, resultDimensions); if (needsDimNames.profile(allEmpty || rowDimResultNames != RNull.instance || colDimResultNames != RNull.instance)) { setDimNames(result, RDataFactory.createList(new Object[]{rowDimResultNames, colDimResultNames})); @@ -684,6 +693,15 @@ public abstract class Bind extends RBaseNode { return result; } + private boolean dimResultNamesComplete(String[] rowDimNamesArray) { + for (String s : rowDimNamesArray) { + if (dimNamesInComplete.profile(s == RRuntime.STRING_NA)) { + return RDataFactory.INCOMPLETE_VECTOR; + } + } + return RDataFactory.COMPLETE_VECTOR; + } + private void setDimNames(RVector<?> result, RList dimNames) { if (setDimNamesNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java index 9fe775ec76542ac41c9933fc3e37c2bc649c464e..fd08cfc07a0c32c57c71217f1f8b1622b053167b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java @@ -17,6 +17,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asStringVect import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.shouldBe; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.typeName; @@ -42,7 +43,22 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; public class BitwiseFunctions { - public abstract static class BasicBitwise extends RBuiltinNode { + protected enum Operation { + AND("bitwAnd"), + OR("bitwOr"), + XOR("bitwXor"), + NOT("bitNot"), + SHIFTR("bitShiftR"), + SHIFTL("bitShiftL"); + + private final String name; + + Operation(String name) { + this.name = name; + } + } + + public abstract static class BasicBitwise extends RBuiltinNode.Arg2 { private final NACheck naCheckA = NACheck.create(); private final NACheck naCheckB = NACheck.create(); @@ -51,21 +67,6 @@ public class BitwiseFunctions { @Child private TypeofNode typeofA = TypeofNodeGen.create(); @Child private TypeofNode typeofB = TypeofNodeGen.create(); - protected enum Operation { - AND("bitwAnd"), - OR("bitwOr"), - XOR("bitwXor"), - NOT("bitNot"), - SHIFTR("bitShiftR"), - SHIFTL("bitShiftL"); - - private final String name; - - Operation(String name) { - this.name = name; - } - } - protected Object basicBit(RAbstractIntVector aVec, RAbstractIntVector bVec, Operation op) { naCheckA.enable(aVec); naCheckB.enable(bVec); @@ -120,14 +121,6 @@ public class BitwiseFunctions { return RDataFactory.createIntVector(ans, completeVector); } - protected Object bitNot(RAbstractIntVector aVec) { - int[] ans = new int[aVec.getLength()]; - for (int i = 0; i < aVec.getLength(); i++) { - ans[i] = ~aVec.getDataAt(i); - } - return RDataFactory.createIntVector(ans, RDataFactory.COMPLETE_VECTOR); - } - protected Object makeNA(int length) { int[] na = new int[length]; for (int i = 0; i < length; i++) { @@ -154,7 +147,7 @@ public class BitwiseFunctions { @Fallback @SuppressWarnings("unused") protected Object differentTypes(Object a, Object b) { - throw RError.error(this, RError.Message.SAME_TYPE, "a", "b"); + throw error(RError.Message.SAME_TYPE, "a", "b"); } } @@ -175,7 +168,7 @@ public class BitwiseFunctions { @Fallback @SuppressWarnings("unused") protected Object differentTypes(Object a, Object b) { - throw RError.error(this, RError.Message.SAME_TYPE, "a", "b"); + throw error(RError.Message.SAME_TYPE, "a", "b"); } } @@ -196,7 +189,7 @@ public class BitwiseFunctions { @Fallback @SuppressWarnings("unused") protected Object differentTypes(Object a, Object b) { - throw RError.error(this, RError.Message.SAME_TYPE, "a", "b"); + throw error(RError.Message.SAME_TYPE, "a", "b"); } } @@ -205,8 +198,9 @@ public class BitwiseFunctions { static { Casts casts = new Casts(BitwiseShiftR.class); - casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.SHIFTR.name).mustBe(doubleValue().or(integerValue())).asIntegerVector(); - casts.arg("n").mapIf(stringValue(), asStringVector(), asIntegerVector()); + casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.SHIFTR.name).mustBe(missingValue().not()).mustBe( + doubleValue().or(integerValue())).asIntegerVector(); + casts.arg("n").allowNull().mustBe(missingValue().not()).mapIf(stringValue(), asStringVector(), asIntegerVector()); } @Specialization @@ -232,10 +226,9 @@ public class BitwiseFunctions { static { Casts casts = new Casts(BitwiseShiftL.class); - casts.arg("a").defaultError(RError.ROOTNODE, RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.SHIFTL.name).mustBe( + casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.SHIFTL.name).mustBe( doubleValue().or(integerValue())).asIntegerVector(); - casts.arg("n").allowNull().mapIf(stringValue(), chain(asStringVector()).with(shouldBe(anyValue().not(), RError.SHOW_CALLER, RError.Message.NA_INTRODUCED_COERCION)).end(), - asIntegerVector()); + casts.arg("n").allowNull().mustNotBeMissing().asIntegerVector(); } @Specialization @@ -248,27 +241,23 @@ public class BitwiseFunctions { protected Object bitwShiftL(RAbstractIntVector a, RNull n) { return RDataFactory.createEmptyIntVector(); } - - @Specialization - @SuppressWarnings("unused") - protected Object bitwShiftLChar(RAbstractVector a, RAbstractStringVector n) { - return makeNA(a.getLength()); - } } @RBuiltin(name = "bitwiseNot", kind = INTERNAL, parameterNames = {"a"}, behavior = PURE) - public abstract static class BitwiseNot extends BasicBitwise { + public abstract static class BitwiseNot extends RBuiltinNode.Arg1 { - // @formatter:off - static { - Casts casts = new Casts(BitwiseNot.class); + static { + Casts casts = new Casts(BitwiseNot.class); casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.NOT.name).mustBe(doubleValue().or(integerValue())).asIntegerVector(); - } - //@formatter:on + } @Specialization protected Object bitwNot(RAbstractIntVector a) { - return bitNot(a); + int[] ans = new int[a.getLength()]; + for (int i = 0; i < a.getLength(); i++) { + ans[i] = ~a.getDataAt(i); + } + return RDataFactory.createIntVector(ans, RDataFactory.COMPLETE_VECTOR); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java index 53812789a2944309cbbdf2ef82272156fee822a9..f481242580767baacdf40fedf6f5ebfc88c71278 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java @@ -25,7 +25,10 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.RASTUtils; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; @@ -34,16 +37,22 @@ import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RNull; @RBuiltin(name = "body", kind = INTERNAL, parameterNames = {"fun"}, behavior = PURE) -public abstract class Body extends RBuiltinNode { +public abstract class Body extends RBuiltinNode.Arg1 { static { Casts.noCasts(Body.class); } @Specialization - protected Object doBody(RFunction fun) { - FunctionDefinitionNode fdn = (FunctionDefinitionNode) fun.getRootNode(); - return RASTUtils.createLanguageElement(fdn.getBody()); + protected Object doBody(RFunction fun, + @Cached("createBinaryProfile()") ConditionProfile profile) { + RootNode root = fun.getRootNode(); + if (profile.profile(root instanceof FunctionDefinitionNode)) { + FunctionDefinitionNode fdn = (FunctionDefinitionNode) root; + return RASTUtils.createLanguageElement(fdn.getBody()); + } else { + return RNull.instance; + } } @Specialization(guards = "!isRFunction(fun)") diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java index 2e2226c33973bc0588b6fa9d509179b91bcd9fa8..8f0f513b5c7f3caaed7217d6668f7b97b57f04ac 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java @@ -22,8 +22,8 @@ */ package com.oracle.truffle.r.nodes.builtin.base; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gt; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; import static com.oracle.truffle.r.runtime.RVisibility.OFF; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; @@ -34,6 +34,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.helpers.BrowserInteractNode; import com.oracle.truffle.r.nodes.builtin.helpers.BrowserInteractNodeGen; @@ -51,7 +52,7 @@ import com.oracle.truffle.r.runtime.instrument.InstrumentationState.BrowserState public class BrowserFunctions { @RBuiltin(name = "browser", visibility = OFF, kind = PRIMITIVE, parameterNames = {"text", "condition", "expr", "skipCalls"}, behavior = COMPLEX) - public abstract static class BrowserNode extends RBuiltinNode { + public abstract static class BrowserNode extends RBuiltinNode.Arg4 { @Child private BrowserInteractNode browserInteractNode = BrowserInteractNodeGen.create(); @@ -99,24 +100,25 @@ public class BrowserFunctions { } } - private abstract static class RetrieveAdapter extends RBuiltinNode { - - static { - Casts casts = new Casts(RetrieveAdapter.class); - casts.arg("n").asIntegerVector().findFirst(0).mustBe(gt(0), Message.POSITIVE_CONTEXTS); - } + protected static void casts(Class<? extends RBuiltinNode> builtinClass) { + Casts casts = new Casts(builtinClass); + casts.arg("n").asIntegerVector().findFirst(0).mustBe(gt(0), Message.POSITIVE_CONTEXTS); + } - /** - * GnuR objects to indices <= 0 but allows positive indices that are out of range. - */ - protected HelperState getHelperState(int n) { - BrowserState helperState = RContext.getInstance().stateInstrumentation.getBrowserState(); - return helperState.get(n); - } + /** + * GnuR objects to indices <= 0 but allows positive indices that are out of range. + */ + protected static HelperState getHelperState(int n) { + BrowserState helperState = RContext.getInstance().stateInstrumentation.getBrowserState(); + return helperState.get(n); } @RBuiltin(name = "browserText", kind = INTERNAL, parameterNames = {"n"}, behavior = COMPLEX) - public abstract static class BrowserText extends RetrieveAdapter { + public abstract static class BrowserText extends RBuiltinNode.Arg1 { + + static { + casts(BrowserText.class); + } @Specialization @TruffleBoundary @@ -126,7 +128,11 @@ public class BrowserFunctions { } @RBuiltin(name = "browserCondition", kind = INTERNAL, parameterNames = {"n"}, behavior = COMPLEX) - public abstract static class BrowserCondition extends RetrieveAdapter { + public abstract static class BrowserCondition extends RBuiltinNode.Arg1 { + + static { + casts(BrowserCondition.class); + } @Specialization @TruffleBoundary @@ -136,7 +142,11 @@ public class BrowserFunctions { } @RBuiltin(name = "browserSetDebug", visibility = OFF, kind = INTERNAL, parameterNames = {"n"}, behavior = COMPLEX) - public abstract static class BrowserSetDebug extends RetrieveAdapter { + public abstract static class BrowserSetDebug extends RBuiltinNode.Arg1 { + + static { + casts(BrowserSetDebug.class); + } @Specialization @TruffleBoundary diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java index 8680eccad330fbf154b34fd6b2760027bd4c48d5..a8223eb1e1d6ff34e2f39304d2fcb89c70f555f3 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java @@ -29,18 +29,17 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.library.utils.Crc64; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "crc64", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) -public abstract class CRC64 extends RBuiltinNode { +public abstract class CRC64 extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(CRC64.class); - casts.arg("x").defaultError(RError.NO_CALLER, Message.INPUT_MUST_BE_STRING).mustBe(stringValue()); + casts.arg("x").defaultError(Message.INPUT_MUST_BE_STRING).mustBe(stringValue()); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CacheClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CacheClass.java index d95ff7128f3770fff7879ddaf065c0641d266c2f..53ac34d5a90d9d66c187ec8eac1ab792ff91361a 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CacheClass.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CacheClass.java @@ -25,7 +25,7 @@ import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = ".cache_class", kind = PRIMITIVE, parameterNames = {"class", "extends"}, behavior = COMPLEX) -public abstract class CacheClass extends RBuiltinNode { +public abstract class CacheClass extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(CacheClass.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java index ed84a24405e3deb35548b798fb1de41f4fb6f895..20b0d7b466b80e2279f2d0fbc23cb9e5b3cf1ff4 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java @@ -32,6 +32,7 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.RASTUtils; +import com.oracle.truffle.r.nodes.access.ConstantNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; @@ -56,7 +57,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; * Does not perform argument matching for first parameter "name". */ @RBuiltin(name = "call", kind = PRIMITIVE, parameterNames = {"", "..."}, behavior = PURE) -public abstract class Call extends RBuiltinNode { +public abstract class Call extends RBuiltinNode.Arg2 { @Override public Object[] getDefaultParameterValues() { @@ -105,6 +106,16 @@ public abstract class Call extends RBuiltinNode { return "function".equals(name) ? makeFunction(args) : makeCall0(ReadVariableNode.createFunctionLookup(RSyntaxNode.LAZY_DEPARSE, name), true, args); } + @TruffleBoundary + protected static RLanguage makeCallSourceUnavailable(int i, RArgsValuesAndNames args) { + return makeCall0(ConstantNode.create(i), true, args); + } + + @TruffleBoundary + protected static RLanguage makeCallSourceUnavailable(double d, RArgsValuesAndNames args) { + return makeCall0(ConstantNode.create(d), true, args); + } + @TruffleBoundary protected static RLanguage makeCallSourceUnavailable(RFunction function, RArgsValuesAndNames args) { return makeCall0(function, true, args); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java index 109ddc233bd053d03bc66ec90a3f0fc9d9e0e74b..8a80bf7e438c3cc9ee71ec83529aebd16dbee763 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java @@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.data.RLogicalVector; import com.oracle.truffle.r.runtime.data.RStringVector; @RBuiltin(name = "capabilities", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) -public abstract class Capabilities extends RBuiltinNode { +public abstract class Capabilities extends RBuiltinNode.Arg0 { private enum Capability { jpeg(false, null), png(false, null), @@ -46,7 +46,7 @@ public abstract class Capabilities extends RBuiltinNode { http_fttp(true, "http/ftp"), sockets(true, null), libxml(false, null), - fifo(false, null), + fifo(true, null), cledit(false, null), iconv(false, null), nls(false, "NLS"), diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java index d1e14444e7d9e2e0985a955a947e8b3622d5c25b..a4b42e74a116a60e55c8384be8784d202d142c7b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java @@ -26,8 +26,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asBoolean; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asInteger; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicLogicalValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyStringVector; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gt0; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; @@ -65,7 +63,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; * The {@code cat .Internal}. */ @RBuiltin(name = "cat", visibility = OFF, kind = INTERNAL, parameterNames = {"arglist", "file", "sep", "fill", "labels", "append"}, behavior = IO) -public abstract class Cat extends RBuiltinNode { +public abstract class Cat extends RBuiltinNode.Arg6 { @Child private ToStringNode toString; @@ -82,9 +80,7 @@ public abstract class Cat extends RBuiltinNode { casts.arg("file").defaultError(Message.INVALID_CONNECTION).mustNotBeNull().asIntegerVector().findFirst(); - casts.arg("fill").mustBe(numericValue()).asVector().mustBe(singleElement()).findFirst().shouldBe( - instanceOf(Byte.class).or(instanceOf(Integer.class).and(gt0())), - Message.NON_POSITIVE_FILL).mapIf(atomicLogicalValue(), asBoolean(), asInteger()); + casts.arg("fill").mustBe(numericValue()).asVector().mustBe(singleElement()).findFirst().mapIf(atomicLogicalValue(), asBoolean(), asInteger()); casts.arg("labels").mapNull(emptyStringVector()).mustBe(stringValue()).asStringVector(); @@ -106,7 +102,9 @@ public abstract class Cat extends RBuiltinNode { @Specialization protected RNull cat(RList args, int file, RAbstractStringVector sepVec, int givenFillWidth, RAbstractStringVector labels, boolean append) { int fillWidth = -1; - if (givenFillWidth >= 1) { + if (givenFillWidth < 0) { + warning(Message.NON_POSITIVE_FILL); + } else if (givenFillWidth >= 1) { fillWidth = givenFillWidth; } return output(args, file, sepVec, fillWidth, labels, append); @@ -193,7 +191,7 @@ public abstract class Cat extends RBuiltinNode { try (RConnection openConn = conn.forceOpen("wt")) { openConn.writeLines(RDataFactory.createStringVectorFromScalar(data), "", false); } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); + throw error(RError.Message.GENERIC, ex.getMessage()); } return RNull.instance; @@ -202,7 +200,7 @@ public abstract class Cat extends RBuiltinNode { private void validateType(int argIndex, Object obj) { if (obj instanceof RList || obj instanceof RLanguage || obj instanceof RExpression) { RTypedValue rType = (RTypedValue) obj; - throw RError.error(this, Message.CAT_ARGUMENT_OF_TYPE, argIndex, rType.getRType().getName()); + throw error(Message.CAT_ARGUMENT_OF_TYPE, argIndex, rType.getRType().getName()); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java index 86c6b72e20b2213e78770ee652c63338a694da7f..166b7545eaa1880ff71f7fc2e9bedd3685a70811 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java @@ -16,7 +16,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -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.builtins.RBuiltin; @@ -25,12 +24,12 @@ import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "charmatch", kind = INTERNAL, parameterNames = {"x", "table", "noMatch"}, behavior = PURE) -public abstract class CharMatch extends RBuiltinNode { +public abstract class CharMatch extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(CharMatch.class); - casts.arg("x").mustBe(stringValue(), RError.NO_CALLER, Message.ARG_IS_NOT_OF_MODE, "character"); - casts.arg("table").mustBe(stringValue(), RError.NO_CALLER, Message.ARG_IS_NOT_OF_MODE, "character"); + casts.arg("x").mustBe(stringValue(), Message.ARG_IS_NOT_OF_MODE, "character"); + casts.arg("table").mustBe(stringValue(), Message.ARG_IS_NOT_OF_MODE, "character"); casts.arg("noMatch").asIntegerVector().findFirst(RRuntime.INT_NA); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java index c72287f73e7e01b29521610aaaefac601bf29f24..ce3302739953a210f01e316de63d8cb28eb8e917 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java @@ -33,7 +33,6 @@ import java.util.function.IntUnaryOperator; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -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; @@ -48,14 +47,14 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; * Binomial coefficients (n, k) for real n and integral k (rounded with warning). */ @RBuiltin(name = "choose", kind = INTERNAL, parameterNames = {"n", "k"}, behavior = PURE) -public abstract class ChooseBuiltin extends RBuiltinNode { +public abstract class ChooseBuiltin extends RBuiltinNode.Arg2 { private final NACheck na = NACheck.create(); static { Casts casts = new Casts(ChooseBuiltin.class); - casts.arg("n").mustBe(numericValue(), RError.SHOW_CALLER, Message.NON_NUMERIC_MATH).mapIf(logicalValue(), asIntegerVector()); - casts.arg("k").mustBe(numericValue(), RError.SHOW_CALLER, Message.NON_NUMERIC_MATH).mapIf(logicalValue(), asIntegerVector()); + casts.arg("n").mustBe(numericValue(), Message.NON_NUMERIC_MATH).mapIf(logicalValue(), asIntegerVector()); + casts.arg("k").mustBe(numericValue(), Message.NON_NUMERIC_MATH).mapIf(logicalValue(), asIntegerVector()); } @Specialization @@ -93,7 +92,7 @@ public abstract class ChooseBuiltin extends RBuiltinNode { double result = Math.round(data); if (result != data) { - RError.warning(this, Message.CHOOSE_ROUNDING_WARNING, data, (int) result); + warning(Message.CHOOSE_ROUNDING_WARNING, data, (int) result); } return (int) result; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Col.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Col.java index 242bce76a30f0d1b7d53f5ce97e6ae316a2e6b92..c331492d3e67f3261451005978ff2da90713c201 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Col.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Col.java @@ -38,11 +38,11 @@ import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @RBuiltin(name = "col", kind = INTERNAL, parameterNames = {"dims"}, behavior = PURE) -public abstract class Col extends RBuiltinNode { +public abstract class Col extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(Col.class); - casts.arg("dims").defaultError(RError.SHOW_CALLER, RError.Message.MATRIX_LIKE_REQUIRED, "col").mustBe(integerValue()).asIntegerVector().mustBe(size(2)); + casts.arg("dims").defaultError(RError.Message.MATRIX_LIKE_REQUIRED, "col").mustBe(integerValue()).asIntegerVector().mustBe(size(2)); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSumsBase.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSumsBase.java index 34215dc57fa37720827f7cbce88ffce610f7ee76..b97bdbc8ffcb6060bc3979abc3558e77c7550c71 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSumsBase.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSumsBase.java @@ -41,23 +41,23 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; * specializations shared between {@link RowSums}, {@link RowMeans}, {@link ColMeans}, * {@link RowSums}. */ -public abstract class ColSumsBase extends RBuiltinNode { +public abstract class ColSumsBase extends RBuiltinNode.Arg4 { protected final NACheck na = NACheck.create(); private final ConditionProfile vectorLengthProfile = ConditionProfile.createBinaryProfile(); protected static Casts createCasts(Class<? extends ColSumsBase> extCls) { Casts casts = new Casts(extCls); - casts.arg("X").mustBe(numericValue(), RError.SHOW_CALLER, RError.Message.X_NUMERIC); - casts.arg("m").defaultError(RError.SHOW_CALLER, INVALID_ARGUMENT, "n").asIntegerVector().findFirst().notNA(RError.NO_CALLER, RError.Message.VECTOR_SIZE_NA); - casts.arg("n").defaultError(RError.SHOW_CALLER, INVALID_ARGUMENT, "p").asIntegerVector().findFirst().notNA(RError.NO_CALLER, RError.Message.VECTOR_SIZE_NA); - casts.arg("na.rm").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("X").mustBe(numericValue(), RError.Message.X_NUMERIC); + casts.arg("m").defaultError(INVALID_ARGUMENT, "n").asIntegerVector().findFirst().mustNotBeNA(RError.Message.VECTOR_SIZE_NA); + casts.arg("n").defaultError(INVALID_ARGUMENT, "p").asIntegerVector().findFirst().mustNotBeNA(RError.Message.VECTOR_SIZE_NA); + casts.arg("na.rm").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); return casts; } protected final void checkVectorLength(RAbstractVector x, int rowNum, int colNum) { if (vectorLengthProfile.profile(x.getLength() < rowNum * colNum)) { - throw RError.error(RError.NO_CALLER, RError.Message.TOO_SHORT, "X"); + throw error(RError.Message.TOO_SHORT, "X"); } } @@ -130,7 +130,7 @@ public abstract class ColSumsBase extends RBuiltinNode { private void checkLengthOne(int rowNum, int colNum) { if (vectorLengthProfile.profile(rowNum * colNum > 1)) { - throw RError.error(RError.NO_CALLER, RError.Message.TOO_SHORT, "X"); + throw error(RError.Message.TOO_SHORT, "X"); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java index 9fa28b86e33fd778f08c9a0d7512b16ddec949b9..90e3aa33b9021ae0ec2cd1bc318904288d560934 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java @@ -25,23 +25,25 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.nodes.NodeInfo; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.base.Colon.ColonCastNode; +import com.oracle.truffle.r.nodes.builtin.base.Colon.ColonInternal; import com.oracle.truffle.r.nodes.builtin.base.ColonNodeGen.ColonCastNodeGen; import com.oracle.truffle.r.nodes.builtin.base.ColonNodeGen.ColonInternalNodeGen; import com.oracle.truffle.r.nodes.unary.CastNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; 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.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDoubleSequence; import com.oracle.truffle.r.runtime.data.RIntSequence; @@ -49,10 +51,33 @@ import com.oracle.truffle.r.runtime.data.RSequence; 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.RAbstractStringVector; +import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.ops.na.NACheck; -@RBuiltin(name = ":", kind = PRIMITIVE, parameterNames = {"", ""}, behavior = PURE) -public abstract class Colon extends RBuiltinNode { +@NodeChild(value = "left", type = RNode.class) +@NodeChild(value = "right", type = RNode.class) +abstract class ColonSpecial extends RNode { + + @Child private ColonCastNode leftCast = ColonCastNodeGen.create(); + @Child private ColonCastNode rightCast = ColonCastNodeGen.create(); + @Child private ColonInternal internal = ColonInternalNodeGen.create(); + + @Specialization + protected Object colon(Object left, Object right) { + return internal.execute(leftCast.doCast(left), rightCast.doCast(right)); + } +} + +// javac fails without fully qualified name +@com.oracle.truffle.r.runtime.builtins.RBuiltin(name = ":", kind = PRIMITIVE, parameterNames = {"", ""}, behavior = PURE) +public abstract class Colon extends RBuiltinNode.Arg2 { + + public static RNode special(ArgumentsSignature signature, RNode[] arguments, boolean inReplacement) { + if (signature.getNonNullCount() == 0 && arguments.length == 2 && !inReplacement) { + return ColonSpecialNodeGen.create(arguments[0], arguments[1]); + } + return null; + } @Child private ColonCastNode leftCast = ColonCastNodeGen.create(); @Child private ColonCastNode rightCast = ColonCastNodeGen.create(); @@ -64,7 +89,7 @@ public abstract class Colon extends RBuiltinNode { @Specialization protected RSequence colon(Object left, Object right) { - return internal.execute(leftCast.execute(left), rightCast.execute(right)); + return internal.execute(leftCast.doCast(left), rightCast.doCast(right)); } @NodeInfo(cost = NodeCost.NONE) @@ -73,13 +98,11 @@ public abstract class Colon extends RBuiltinNode { private final NACheck leftNA = NACheck.create(); private final NACheck rightNA = NACheck.create(); - private final BranchProfile naCheckErrorProfile = BranchProfile.create(); - abstract RSequence execute(Object left, Object right); private void naCheck(boolean na) { if (na) { - naCheckErrorProfile.enter(); + CompilerDirectives.transferToInterpreter(); throw RError.error(this, RError.Message.NA_OR_NAN); } } @@ -155,6 +178,7 @@ public abstract class Colon extends RBuiltinNode { } } + @NodeInfo(cost = NodeCost.NONE) abstract static class ColonCastNode extends CastNode { private final ConditionProfile lengthGreaterOne = ConditionProfile.createBinaryProfile(); @@ -177,10 +201,10 @@ public abstract class Colon extends RBuiltinNode { private void checkLength(int length) { if (lengthGreaterOne.profile(length > 1)) { - RError.warning(this, RError.Message.ONLY_FIRST_USED, length); + warning(RError.Message.ONLY_FIRST_USED, length); } if (lengthEqualsZero.profile(length == 0)) { - throw RError.error(this, Message.ARGUMENT_LENGTH_0); + throw error(Message.ARGUMENT_LENGTH_0); } } @@ -212,21 +236,20 @@ public abstract class Colon extends RBuiltinNode { checkLength(vector.getLength()); String val = vector.getDataAt(0); if (RRuntime.isNA(val)) { - throw RError.error(this, RError.Message.NA_OR_NAN); + throw error(RError.Message.NA_OR_NAN); } // TODO it might be a double or complex string int result = RRuntime.string2intNoCheck(val); if (RRuntime.isNA(result)) { - RError.warning(this, RError.Message.NA_INTRODUCED_COERCION); - throw RError.error(this, RError.Message.NA_OR_NAN); + warning(RError.Message.NA_INTRODUCED_COERCION); + throw error(RError.Message.NA_OR_NAN); } return result; } @Fallback - @TruffleBoundary protected int doOther(@SuppressWarnings("unused") Object value) { - throw RError.error(this, Message.ARGUMENT_LENGTH_0); + throw error(Message.ARGUMENT_LENGTH_0); } protected static boolean isIntValue(double d) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java index 1e068b47c7802987bc7b3c80b8362fc3a6d8819c..4900debc6e7727015a5a17970fcee10d1d3caab1 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java @@ -41,16 +41,16 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.nodes.ExplodeLoop; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.builtin.base.CombineNodeGen.CombineInputCastNodeGen; import com.oracle.truffle.r.nodes.unary.CastComplexNodeGen; import com.oracle.truffle.r.nodes.unary.CastDoubleNodeGen; import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen; @@ -76,11 +76,10 @@ import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.nodes.RBaseNode; -import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "c", kind = PRIMITIVE, parameterNames = {"...", "recursive"}, dispatch = INTERNAL_GENERIC, behavior = PURE) -public abstract class Combine extends RBuiltinNode { +public abstract class Combine extends RBuiltinNode.Arg2 { public static Combine create() { return CombineNodeGen.create(); @@ -90,10 +89,11 @@ public abstract class Combine extends RBuiltinNode { protected static final int COMBINE_CACHED_LIMIT = PrecedenceNode.NUMBER_OF_PRECEDENCES; - private static final int MAX_PROFILES = 4; + private static final int MAX_PROFILES = 8; @Child private PrecedenceNode precedenceNode = PrecedenceNodeGen.create(); - @Child private CombineInputCast inputCast = CombineInputCastNodeGen.create(null); + @Children private final CombineInputCast[] inputCasts = new CombineInputCast[MAX_PROFILES]; + @Child private CombineInputCast overflowInputCast; @Child private CastToVectorNode castVector; private final BranchProfile naBranch = BranchProfile.create(); @@ -101,11 +101,10 @@ public abstract class Combine extends RBuiltinNode { private final ConditionProfile fastNamesMerge = ConditionProfile.createBinaryProfile(); private final ConditionProfile isAbstractVectorProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile hasNewNamesProfile = ConditionProfile.createBinaryProfile(); - @CompilationFinal private final ValueProfile[] argProfiles = new ValueProfile[MAX_PROFILES]; static { Casts casts = new Casts(Combine.class); - casts.arg("recursive").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean()); + casts.arg("recursive").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); } public abstract Object executeCombine(Object value, Object recursive); @@ -119,10 +118,24 @@ public abstract class Combine extends RBuiltinNode { return args.getArgument(0); } + private CombineInputCast getCast(int index) { + CombineInputCast cast = index < MAX_PROFILES ? inputCasts[index] : overflowInputCast; + if (cast == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + cast = insert(new CombineInputCast()); + if (index < MAX_PROFILES) { + inputCasts[index] = cast; + } else { + overflowInputCast = cast; + } + } + return cast; + } + @Specialization(replaces = "combineSimple", limit = "1", guards = {"!recursive", "args.getSignature() == cachedSignature", "cachedPrecedence == precedence(args, cachedSignature.getLength())"}) protected Object combineCached(RArgsValuesAndNames args, @SuppressWarnings("unused") boolean recursive, @Cached("args.getSignature()") ArgumentsSignature cachedSignature, - @Cached("precedence( args, cachedSignature.getLength())") int cachedPrecedence, + @Cached("precedence(args, cachedSignature.getLength())") int cachedPrecedence, @Cached("createCast(cachedPrecedence)") CastNode cast, @Cached("create()") BranchProfile naNameBranch, @Cached("create()") NACheck naNameCheck, @@ -172,9 +185,7 @@ public abstract class Combine extends RBuiltinNode { return combineRecursive(args, recursiveCombine, useNewArgsProfile); } - @SuppressWarnings("static-method") - @ExplodeLoop - private Object combineRecursive(RArgsValuesAndNames args, Combine recursiveCombine, ConditionProfile useNewArgsProfile) { + private static Object combineRecursive(RArgsValuesAndNames args, Combine recursiveCombine, ConditionProfile useNewArgsProfile) { Object[] argsArray = args.getArguments(); Object[] newArgsArray = new Object[argsArray.length]; boolean useNewArgs = false; @@ -202,14 +213,10 @@ public abstract class Combine extends RBuiltinNode { private int prepareElements(Object[] args, CastNode cast, int precedence, Object[] elements) { int size = 0; for (int i = 0; i < elements.length; i++) { - Object element = readAndCast(cast, args[i], precedence); - if (i < argProfiles.length) { - if (argProfiles[i] == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - argProfiles[i] = ValueProfile.createClassProfile(); - } - element = argProfiles[i].profile(element); - } + CombineInputCast inputCast = getCast(i); + Object value = args[i]; + Object element = (precedence == EXPRESSION_PRECEDENCE && value instanceof RLanguage) ? value : cast.doCast(inputCast.cast(value)); + element = inputCast.valueProfile.profile(element); elements[i] = element; size += getElementSize(element); } @@ -230,10 +237,7 @@ public abstract class Combine extends RBuiltinNode { @ExplodeLoop private boolean hasNames(Object[] elements, GetNamesAttributeNode getNamesNode) { for (int i = 0; i < elements.length; i++) { - Object element = elements[i]; - if (i < argProfiles.length) { - element = argProfiles[i].profile(element); - } + Object element = getCast(i).valueProfile.profile(elements[i]); if (element instanceof RAbstractVector) { RAbstractVector vector = (RAbstractVector) element; if (getNamesNode.getNames(vector) != null) { @@ -250,10 +254,7 @@ public abstract class Combine extends RBuiltinNode { result.incRefCount(); int pos = 0; for (int i = 0; i < elements.length; i++) { - Object element = elements[i]; - if (i < argProfiles.length) { - element = argProfiles[i].profile(element); - } + Object element = getCast(i).valueProfile.profile(elements[i]); pos += processNamesElement(naNameBranch, naNameCheck, result, pos, element, i, signature, getNamesNode); } return result; @@ -302,7 +303,8 @@ public abstract class Combine extends RBuiltinNode { private RVector<?> foldContents(int cachedPrecedence, Object[] elements, int size, RStringVector namesVector) { RVector<?> result = createResultVector(cachedPrecedence, size, namesVector); int pos = 0; - for (Object element : elements) { + for (int i = 0; i < elements.length; i++) { + Object element = getCast(i).valueProfile.profile(elements[i]); pos += processContentElement(result, pos, element); } return result; @@ -339,11 +341,6 @@ public abstract class Combine extends RBuiltinNode { return combine.executeCombine(new RArgsValuesAndNames(new Object[]{args}, EMPTY_SIGNATURE), recursive); } - private Object readAndCast(CastNode castNode, Object arg, int precedence) { - Object value = inputCast.execute(arg); - return (precedence == EXPRESSION_PRECEDENCE && value instanceof RLanguage) ? value : castNode.execute(value); - } - protected int precedence(RArgsValuesAndNames args) { int precedence = NO_PRECEDENCE; Object[] array = args.getArguments(); @@ -382,9 +379,9 @@ public abstract class Combine extends RBuiltinNode { case RAW_PRECEDENCE: return RDataFactory.createRawVector(new byte[size], names); case EXPRESSION_PRECEDENCE: - return RDataFactory.createExpression(new Object[size], names); + return RDataFactory.createExpression(size, names); case LIST_PRECEDENCE: - return RDataFactory.createList(new Object[size], names); + return RDataFactory.createList(size, names); case NO_PRECEDENCE: return null; default: @@ -455,49 +452,59 @@ public abstract class Combine extends RBuiltinNode { return names; } - @NodeChild - protected abstract static class CombineInputCast extends RNode { - - @Child private GetDimNamesAttributeNode getDimNamesNode = GetDimNamesAttributeNode.create(); - @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create(); - - public abstract Object execute(Object operand); + protected static final class CombineInputCast extends Node { - @Specialization(guards = "!isVector(operand)") - protected Object pass(Object operand) { - return operand; - } + @Child private GetDimNamesAttributeNode getDimNamesNode; + @Child private GetNamesAttributeNode getNamesNode; - protected static boolean isVector(Object operand) { - return operand instanceof RVector; - } + private final ValueProfile valueProfile = ValueProfile.createClassProfile(); + private final ValueProfile inputValueProfile = ValueProfile.createClassProfile(); - @Specialization(guards = "needsCopy(vector)") - protected RAbstractVector noCopy(RAbstractVector vector, - @Cached("createBinaryProfile()") ConditionProfile hasNamesProfile, - @Cached("createBinaryProfile()") ConditionProfile hasDimNamesProfile) { - RVector<?> materialized = vector.materialize(); - RVector<?> result = materialized.copyDropAttributes(); + @CompilationFinal private ConditionProfile hasNamesProfile; + @CompilationFinal private ConditionProfile hasDimNamesProfile; - RStringVector vecNames = getNamesNode.getNames(materialized); - if (hasNamesProfile.profile(vecNames != null)) { - result.initAttributes(RAttributesLayout.createNames(vecNames)); - } else { - RList dimNames = getDimNamesNode.getDimNames(materialized); - if (hasDimNamesProfile.profile(dimNames != null)) { - result.initAttributes(RAttributesLayout.createDimNames(dimNames)); + public Object cast(Object operand) { + Object profiled = inputValueProfile.profile(operand); + if (profiled instanceof RVector<?>) { + RVector<?> vector = (RVector<?>) profiled; + if (vector.getAttributes() != null) { + if (getNamesNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getNamesNode = insert(GetNamesAttributeNode.create()); + } + if (hasNamesProfile == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + hasNamesProfile = ConditionProfile.createBinaryProfile(); + } + RStringVector vecNames = getNamesNode.getNames(vector); + if (hasNamesProfile.profile(vecNames != null)) { + RVector<?> result = vector.copyDropAttributes(); + result.initAttributes(RAttributesLayout.createNames(vecNames)); + return result; + } else { + if (getDimNamesNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getDimNamesNode = insert(GetDimNamesAttributeNode.create()); + } + if (hasDimNamesProfile == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + hasDimNamesProfile = ConditionProfile.createBinaryProfile(); + } + RList dimNames = getDimNamesNode.getDimNames(vector); + if (hasDimNamesProfile.profile(dimNames != null)) { + RVector<?> result = vector.copyDropAttributes(); + result.initAttributes(RAttributesLayout.createDimNames(dimNames)); + return result; + } + } } } - return result; - } - - @Specialization(guards = "!needsCopy(vector)") - protected RAbstractVector prepareVector(RAbstractVector vector) { - return vector; + return profiled; } - protected boolean needsCopy(RAbstractVector vector) { - return vector.getAttributes() != null || getNamesNode.getNames(vector) != null || getDimNamesNode.getDimNames(vector) != null; + @Override + public NodeCost getCost() { + return NodeCost.NONE; } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.java index f2ad7c85cf048e88215dbd78575d5baebe2ab7b6..9c6f24083b497de96d5c22cfa60eee2b21e33741 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.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 @@ -34,7 +34,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RStringVector; @RBuiltin(name = "commandArgs", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) -public abstract class CommandArgs extends RBuiltinNode { +public abstract class CommandArgs extends RBuiltinNode.Arg0 { @Specialization @TruffleBoundary diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CompileFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CompileFunctions.java index 7fb2b3ce4d4c9c558cda43fd5bff4ff849c9a436..515a446f104eff8d27cd9562b20f4507c3a0e4ba 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CompileFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CompileFunctions.java @@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; public class CompileFunctions { @RBuiltin(name = "compilePKGS", kind = INTERNAL, parameterNames = "enable", behavior = PURE) - public abstract static class CompilePKGS extends RBuiltinNode { + public abstract static class CompilePKGS extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(CompilePKGS.class); @@ -49,7 +49,7 @@ public class CompileFunctions { } @RBuiltin(name = "enableJIT", kind = INTERNAL, parameterNames = "level", behavior = PURE) - public abstract static class EnableJIT extends RBuiltinNode { + public abstract static class EnableJIT extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(EnableJIT.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Complex.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Complex.java index f8826494d7df98c923ecb41e5cdad4ec5a076837..2034744f3a4871d87cb00d21174b0bf48838ff73 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Complex.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Complex.java @@ -23,6 +23,7 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -39,13 +40,13 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "complex", kind = INTERNAL, parameterNames = {"length.out", "real", "imaginary"}, behavior = PURE) -public abstract class Complex extends RBuiltinNode { +public abstract class Complex extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(Complex.class); casts.arg("length.out").asIntegerVector().findFirst(Message.INVALID_LENGTH); - casts.arg("real").mapNull(emptyDoubleVector()).asDoubleVector(); - casts.arg("imaginary").mapNull(emptyDoubleVector()).asDoubleVector(); + casts.arg("real").mustNotBeMissing().mapIf(nullValue(), emptyDoubleVector()).asDoubleVector(); + casts.arg("imaginary").mustNotBeMissing().mapIf(nullValue(), emptyDoubleVector()).asDoubleVector(); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java index b56352f79199d784967ff6027ba18aa6da154b96..12fffb616a49f19672854e6aa2d57c0c22326559 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java @@ -28,7 +28,6 @@ import com.oracle.truffle.api.frame.FrameSlotTypeException; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; -import com.oracle.truffle.r.nodes.function.PromiseHelperNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RErrorHandling; import com.oracle.truffle.r.runtime.RInternalError; @@ -43,20 +42,8 @@ import com.oracle.truffle.r.runtime.env.REnvironment; */ public class ConditionFunctions { - public abstract static class EvalAdapter extends RBuiltinNode { - @Child private PromiseHelperNode promiseHelper; - - protected PromiseHelperNode initPromiseHelper() { - if (promiseHelper == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - promiseHelper = insert(new PromiseHelperNode()); - } - return promiseHelper; - } - } - @RBuiltin(name = ".addCondHands", visibility = OFF, kind = INTERNAL, parameterNames = {"classes", "handlers", "parentenv", "target", "calling"}, behavior = COMPLEX) - public abstract static class AddCondHands extends RBuiltinNode { + public abstract static class AddCondHands extends RBuiltinNode.Arg5 { static { Casts casts = new Casts(AddCondHands.class); @@ -81,7 +68,7 @@ public class ConditionFunctions { @Cached("createHandlerFrameSlot(frame)") FrameSlot handlerFrameSlot) { if (classes.getLength() != handlers.getLength()) { CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.BAD_HANDLER_DATA); + throw error(RError.Message.BAD_HANDLER_DATA); } try { if (!frame.isObject(handlerFrameSlot) || frame.getObject(handlerFrameSlot) == null) { @@ -100,7 +87,12 @@ public class ConditionFunctions { } @RBuiltin(name = ".resetCondHands", visibility = OFF, kind = INTERNAL, parameterNames = {"stack"}, behavior = COMPLEX) - public abstract static class ResetCondHands extends RBuiltinNode { + public abstract static class ResetCondHands extends RBuiltinNode.Arg1 { + + static { + Casts.noCasts(ResetCondHands.class); + } + @SuppressWarnings("unused") @Specialization protected RNull resetCondHands(Object stack) { @@ -109,24 +101,12 @@ public class ConditionFunctions { } } - public abstract static class RestartAdapter extends RBuiltinNode { - protected void checkLength(RList restart) { - if (restart.getLength() < 2) { - throw RError.error(this, RError.Message.BAD_RESTART); - } - } - - protected static void restart(Casts casts) { - casts.arg("restart").mustBe(instanceOf(RList.class), RError.Message.BAD_RESTART); - } - } - @RBuiltin(name = ".addRestart", kind = INTERNAL, parameterNames = "restart", behavior = COMPLEX) - public abstract static class AddRestart extends RestartAdapter { + public abstract static class AddRestart extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(AddRestart.class); - restart(casts); + casts.arg("restart").mustBe(instanceOf(RList.class), RError.Message.BAD_RESTART); } protected FrameSlot createRestartFrameSlot(VirtualFrame frame) { @@ -136,7 +116,9 @@ public class ConditionFunctions { @Specialization protected Object addRestart(VirtualFrame frame, RList restart, @Cached("createRestartFrameSlot(frame)") FrameSlot restartFrameSlot) { - checkLength(restart); + if (restart.getLength() < 2) { + throw error(RError.Message.BAD_RESTART); + } try { if (!frame.isObject(restartFrameSlot) || frame.getObject(restartFrameSlot) == null) { frame.setObject(restartFrameSlot, RErrorHandling.getRestartStack()); @@ -150,7 +132,7 @@ public class ConditionFunctions { } @RBuiltin(name = ".getRestart", kind = INTERNAL, parameterNames = "restart", behavior = COMPLEX) - public abstract static class GetRestart extends RBuiltinNode { + public abstract static class GetRestart extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(GetRestart.class); @@ -165,27 +147,27 @@ public class ConditionFunctions { } @RBuiltin(name = ".invokeRestart", kind = INTERNAL, parameterNames = {"restart", "args"}, behavior = COMPLEX) - public abstract static class InvokeRestart extends RestartAdapter { + public abstract static class InvokeRestart extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(InvokeRestart.class); - restart(casts); + casts.arg("restart").mustBe(instanceOf(RList.class), RError.Message.BAD_RESTART); } @Specialization @TruffleBoundary protected RNull invokeRestart(RList restart, Object args) { - checkLength(restart); - if (RErrorHandling.invokeRestart(restart, args) == null) { - throw RError.error(this, RError.Message.RESTART_NOT_ON_STACK); - } else { - return RNull.instance; // not reached + if (restart.getLength() < 2) { + throw error(RError.Message.BAD_RESTART); } + RErrorHandling.invokeRestart(restart, args); + // invokeRestart is expected to always return via a ReturnException + throw error(RError.Message.RESTART_NOT_ON_STACK); } } @RBuiltin(name = ".signalCondition", kind = INTERNAL, parameterNames = {"condition", "msg", "call"}, behavior = COMPLEX) - public abstract static class SignalCondition extends RBuiltinNode { + public abstract static class SignalCondition extends RBuiltinNode.Arg3 { static { Casts.noCasts(SignalCondition.class); @@ -199,7 +181,7 @@ public class ConditionFunctions { } @RBuiltin(name = "geterrmessage", kind = INTERNAL, parameterNames = {}, behavior = COMPLEX) - public abstract static class Geterrmessage extends RBuiltinNode { + public abstract static class Geterrmessage extends RBuiltinNode.Arg0 { @Specialization protected String geterrmessage() { return RErrorHandling.geterrmessage(); @@ -207,7 +189,7 @@ public class ConditionFunctions { } @RBuiltin(name = "seterrmessage", visibility = OFF, kind = INTERNAL, parameterNames = "msg", behavior = COMPLEX) - public abstract static class Seterrmessage extends RBuiltinNode { + public abstract static class Seterrmessage extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(Seterrmessage.class); @@ -222,7 +204,7 @@ public class ConditionFunctions { } @RBuiltin(name = ".dfltWarn", kind = INTERNAL, parameterNames = {"message", "call"}, behavior = COMPLEX) - public abstract static class DfltWarn extends RBuiltinNode { + public abstract static class DfltWarn extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(DfltWarn.class); @@ -237,7 +219,7 @@ public class ConditionFunctions { } @RBuiltin(name = ".dfltStop", kind = INTERNAL, parameterNames = {"message", "call"}, behavior = COMPLEX) - public abstract static class DfltStop extends RBuiltinNode { + public abstract static class DfltStop extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(DfltStop.class); @@ -252,7 +234,7 @@ public class ConditionFunctions { } @RBuiltin(name = "printDeferredWarnings", visibility = OFF, kind = INTERNAL, parameterNames = {}, behavior = COMPLEX) - public abstract static class PrintDeferredWarnings extends RBuiltinNode { + public abstract static class PrintDeferredWarnings extends RBuiltinNode.Arg0 { @Specialization @TruffleBoundary protected RNull printDeferredWarnings() { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java index 59a02ba8003fad19929e6112d91fe9f67f10fe03..272c1ea4e83234bd361da44fc135b4fff3bb44de 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java @@ -23,6 +23,7 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asIntegerVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.equalTo; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.findFirst; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte; @@ -31,6 +32,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalTrue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lte; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.rawValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; @@ -47,16 +49,23 @@ import static com.oracle.truffle.r.runtime.conn.StdConnections.getStdout; import java.io.IOException; import java.net.MalformedURLException; +import java.net.URL; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.DoubleBuffer; import java.nio.IntBuffer; +import java.nio.ShortBuffer; +import java.nio.channels.ByteChannel; +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; import java.util.ArrayList; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.TypeSystemReference; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.java.JavaInterop; import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.ConnectionFunctionsFactory.WriteDataNodeGen; @@ -67,10 +76,15 @@ import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; -import com.oracle.truffle.r.runtime.conn.CompressedConnections.CompressedRConnection; +import com.oracle.truffle.r.runtime.builtins.RBuiltinKind; +import com.oracle.truffle.r.runtime.conn.ChannelConnections.ChannelRConnection; import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection; +import com.oracle.truffle.r.runtime.conn.FifoConnections.FifoRConnection; +import com.oracle.truffle.r.runtime.conn.FileConnections.CompressedRConnection; import com.oracle.truffle.r.runtime.conn.FileConnections.FileRConnection; +import com.oracle.truffle.r.runtime.conn.PipeConnections.PipeRConnection; import com.oracle.truffle.r.runtime.conn.RConnection; +import com.oracle.truffle.r.runtime.conn.RawConnections.RawRConnection; import com.oracle.truffle.r.runtime.conn.SocketConnections.RSocketConnection; import com.oracle.truffle.r.runtime.conn.TextConnections.TextRConnection; import com.oracle.truffle.r.runtime.conn.URLConnections.URLRConnection; @@ -83,12 +97,14 @@ import com.oracle.truffle.r.runtime.data.RExpression; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RRaw; import com.oracle.truffle.r.runtime.data.RRawVector; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RTypes; import com.oracle.truffle.r.runtime.data.RVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @@ -108,7 +124,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; */ public abstract class ConnectionFunctions { @RBuiltin(name = "stdin", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) - public abstract static class Stdin extends RBuiltinNode { + public abstract static class Stdin extends RBuiltinNode.Arg0 { @Specialization @TruffleBoundary protected RAbstractIntVector stdin() { @@ -117,7 +133,7 @@ public abstract class ConnectionFunctions { } @RBuiltin(name = "stdout", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) - public abstract static class Stdout extends RBuiltinNode { + public abstract static class Stdout extends RBuiltinNode.Arg0 { @Specialization @TruffleBoundary protected RAbstractIntVector stdout() { @@ -126,7 +142,7 @@ public abstract class ConnectionFunctions { } @RBuiltin(name = "stderr", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) - public abstract static class Stderr extends RBuiltinNode { + public abstract static class Stderr extends RBuiltinNode.Arg0 { @Specialization @TruffleBoundary protected RAbstractIntVector stderr() { @@ -135,12 +151,17 @@ public abstract class ConnectionFunctions { } public static final class CastsHelper { - private static void description(Casts casts) { - casts.arg("description").mustBe(stringValue()).asStringVector().shouldBe(singleElement(), RError.Message.ARGUMENT_ONLY_FIRST_1, "description").findFirst().notNA(); + private static HeadPhaseBuilder<String> description(Casts casts) { + return casts.arg("description").mustBe(stringValue()).asStringVector().shouldBe(singleElement(), RError.Message.ARGUMENT_ONLY_FIRST_1, "description").findFirst().mustNotBeNA(); } private static HeadPhaseBuilder<String> open(Casts casts) { - return casts.arg("open").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().notNA(); + return casts.arg("open").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().mustNotBeNA(); + } + + private static HeadPhaseBuilder<String> openMode(Casts casts) { + return open(casts).mustBe(equalTo("").or(equalTo("r")).or(equalTo("rt")).or(equalTo("rb")).or(equalTo("r+")).or(equalTo("r+b")).or(equalTo("w")).or(equalTo("wt")).or(equalTo("wb")).or( + equalTo("w+")).or(equalTo("w+b")).or(equalTo("a")).or(equalTo("a+")), RError.Message.UNSUPPORTED_MODE); } private static void encoding(Casts casts) { @@ -148,11 +169,11 @@ public abstract class ConnectionFunctions { } private static void raw(Casts casts) { - casts.arg("raw").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("raw").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } private static void blocking(Casts casts) { - casts.arg("blocking").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("blocking").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } public static void connection(Casts casts) { @@ -160,11 +181,11 @@ public abstract class ConnectionFunctions { } private static void nchars(Casts casts) { - casts.arg("nchars").asIntegerVector().mustBe(notEmpty()); + casts.arg("nchars").mustNotBeMissing().mapIf(nullValue(), constant(0)).asIntegerVector().mustBe(notEmpty()); } private static void useBytes(Casts casts) { - casts.arg("useBytes").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("useBytes").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } private static void n(Casts casts) { @@ -176,22 +197,26 @@ public abstract class ConnectionFunctions { } private static void swap(Casts casts) { - casts.arg("swap").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("swap").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } private static void method(Casts casts) { - casts.arg("method").asStringVector().findFirst(); + casts.arg("method").asStringVector().findFirst().mustBe(equalTo("default").or(equalTo("internal")), RError.Message.UNSUPPORTED_URL_METHOD); + } + + static void blockingNotSupported(Casts casts) { + casts.arg("blocking").asLogicalVector().findFirst().mustBe(logicalTrue(), RError.Message.NYI, "non-blocking mode not supported").map(toBoolean()); } } @RBuiltin(name = "file", kind = INTERNAL, parameterNames = {"description", "open", "blocking", "encoding", "method", "raw"}, behavior = IO) - public abstract static class File extends RBuiltinNode { + public abstract static class File extends RBuiltinNode.Arg6 { static { Casts casts = new Casts(File.class); CastsHelper.description(casts); CastsHelper.open(casts); - casts.arg("blocking").asLogicalVector().findFirst().mustBe(logicalTrue(), RError.Message.NYI, "non-blocking mode not supported").map(toBoolean()); + CastsHelper.blocking(casts); CastsHelper.encoding(casts); CastsHelper.method(casts); CastsHelper.raw(casts); @@ -199,11 +224,25 @@ public abstract class ConnectionFunctions { @Specialization @TruffleBoundary - @SuppressWarnings("unused") - protected RAbstractIntVector file(String description, String openArg, boolean blocking, String encoding, String method, boolean raw) { + protected RAbstractIntVector file(String description, String openArg, boolean blocking, String encoding, @SuppressWarnings("unused") String method, boolean raw) { String open = openArg; - // TODO handle http/ftp prefixes and redirect and method - String path = removeFileURLPrefix(description); + + // check if the description is an URL and dispatch if necessary + String path = description; + try { + URL url = new URL(description); + if (!"file".equals(url.getProtocol())) { + return new URLRConnection(description, open, encoding).asVector(); + } else { + path = removeFileURLPrefix(description); + } + } catch (MalformedURLException e) { + // ignore and try to open file + } catch (IOException e) { + RError.warning(RError.SHOW_CALLER, RError.Message.UNABLE_TO_RESOLVE, e.getMessage()); + throw error(RError.Message.CANNOT_OPEN_CONNECTION); + } + if (path.length() == 0) { // special case, temp file opened in "w+" or "w+b" only if (open.length() == 0) { @@ -211,15 +250,17 @@ public abstract class ConnectionFunctions { } else { if (!(open.equals("w+") || open.equals("w+b"))) { open = "w+"; - RError.warning(this, RError.Message.FILE_OPEN_TMP); + warning(RError.Message.FILE_OPEN_TMP); } } } try { - return new FileRConnection(path, open).asVector(); + return new FileRConnection(description, path, open, blocking, encoding, raw, true).asVector(); } catch (IOException ex) { - RError.warning(this, RError.Message.CANNOT_OPEN_FILE, description, ex.getMessage()); - throw RError.error(this, RError.Message.CANNOT_OPEN_CONNECTION); + warning(RError.Message.CANNOT_OPEN_FILE, description, ex.getMessage()); + throw error(RError.Message.CANNOT_OPEN_CONNECTION); + } catch (IllegalCharsetNameException ex) { + throw error(RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, ""); } } } @@ -229,7 +270,7 @@ public abstract class ConnectionFunctions { * uncompressed files, and files compressed by {@code bzip2, xz, lzma}. */ - public abstract static class ZZFileAdapter extends RBuiltinNode { + public abstract static class ZZFileAdapter extends RBuiltinNode.Arg4 { private final RCompression.Type cType; protected ZZFileAdapter(RCompression.Type cType) { @@ -241,23 +282,25 @@ public abstract class ConnectionFunctions { CastsHelper.description(casts); CastsHelper.open(casts); CastsHelper.encoding(casts); - casts.arg("compression").asIntegerVector().findFirst().notNA().mustBe(gte(cType == RCompression.Type.XZ ? -9 : 0).and(lte(9))); + casts.arg("compression").asIntegerVector().findFirst().mustNotBeNA().mustBe(gte(cType == RCompression.Type.XZ ? -9 : 0).and(lte(9))); return casts; } @Specialization @TruffleBoundary - protected RAbstractIntVector zzFile(RAbstractStringVector description, String open, String encoding, int compression) { + protected RAbstractIntVector zzFile(String description, String open, String encoding, int compression) { try { - return new CompressedRConnection(description.getDataAt(0), open, cType, encoding, compression).asVector(); + return new CompressedRConnection(description, open, cType, encoding, compression).asVector(); } catch (IOException ex) { - throw reportError(description.getDataAt(0), ex); + throw reportError(description, ex); + } catch (IllegalCharsetNameException ex) { + throw error(RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, ""); } } private RError reportError(String path, IOException ex) throws RError { - RError.warning(this, RError.Message.CANNOT_OPEN_FILE, path, ex.getMessage()); - throw RError.error(this, RError.Message.CANNOT_OPEN_CONNECTION); + warning(RError.Message.CANNOT_OPEN_FILE, path, ex.getMessage()); + throw error(RError.Message.CANNOT_OPEN_CONNECTION); } } @@ -295,55 +338,35 @@ public abstract class ConnectionFunctions { } @RBuiltin(name = "textConnection", kind = INTERNAL, parameterNames = {"description", "text", "open", "env", "encoding"}, behavior = IO) - public abstract static class TextConnection extends RBuiltinNode { + public abstract static class TextConnection extends RBuiltinNode.Arg5 { static { Casts casts = new Casts(TextConnection.class); CastsHelper.description(casts); - // TODO how to have either a RNull or a String/RStringVector and have the latter coerced - // to a - // RAbstractStringVector to avoid the explicit handling in the specialization casts.arg("text").allowNull().mustBe(stringValue()); CastsHelper.open(casts).mustBe(equalTo("").or(equalTo("r").or(equalTo("w").or(equalTo("a")))), RError.Message.UNSUPPORTED_MODE); casts.arg("env").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class)); - casts.arg("encoding").asIntegerVector().findFirst().notNA(); - } - - private static RAbstractStringVector forceStringVector(Object text) { - if (text instanceof String) { - return RDataFactory.createStringVectorFromScalar((String) text); - } else { - return (RAbstractStringVector) text; - } + casts.arg("encoding").asIntegerVector().findFirst().mustNotBeNA(); } @Specialization @TruffleBoundary - protected RAbstractIntVector textConnection(String description, Object text, String open, REnvironment env, @SuppressWarnings("unused") int encoding) { - RAbstractStringVector object; - if (open.length() == 0 || open.equals("r")) { - if (text == RNull.instance) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "text"); - } else { - object = forceStringVector(text); - } - } else { - if (text == RNull.instance) { - throw RError.nyi(this, "textConnection: NULL"); - } else { - object = forceStringVector(text); - } - } + protected RAbstractIntVector textConnection(String description, RAbstractStringVector text, String open, REnvironment env, @SuppressWarnings("unused") int encoding) { try { - return new TextRConnection(description, object, env, open).asVector(); + return new TextRConnection(description, text, env, open).asVector(); } catch (IOException ex) { throw RInternalError.shouldNotReachHere(); } } + + @Specialization + protected RAbstractIntVector textConnection(String description, @SuppressWarnings("unused") RNull text, String open, REnvironment env, int encoding) { + return textConnection(description, (RAbstractStringVector) null, open, env, encoding); + } } @RBuiltin(name = "textConnectionValue", kind = INTERNAL, parameterNames = {"con"}, behavior = IO) - public abstract static class TextConnectionValue extends RBuiltinNode { + public abstract static class TextConnectionValue extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(TextConnectionValue.class); @@ -352,24 +375,24 @@ public abstract class ConnectionFunctions { @Specialization @TruffleBoundary - protected Object textConnection(int con) { + protected RAbstractStringVector textConnection(int con) { RConnection connection = RConnection.fromIndex(con); if (connection instanceof TextRConnection) { - return RDataFactory.createStringVector(((TextRConnection) connection).getValue(), RDataFactory.COMPLETE_VECTOR); + return ((TextRConnection) connection).getValue(); } else { - throw RError.error(RError.SHOW_CALLER, Message.NOT_A_TEXT_CONNECTION); + throw error(Message.NOT_A_TEXT_CONNECTION); } } } @RBuiltin(name = "socketConnection", kind = INTERNAL, parameterNames = {"host", "port", "server", "blocking", "open", "encoding", "timeout"}, behavior = IO) - public abstract static class SocketConnection extends RBuiltinNode { + public abstract static class SocketConnection extends RBuiltinNode.Arg7 { static { Casts casts = new Casts(SocketConnection.class); casts.arg("host").mustBe(stringValue()).asStringVector().findFirst(); - casts.arg("port").asIntegerVector().findFirst().notNA().mustBe(gte(0)); - casts.arg("server").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("port").asIntegerVector().findFirst().mustNotBeNA().mustBe(gte(0)); + casts.arg("server").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); CastsHelper.open(casts); CastsHelper.blocking(casts); casts.arg("timeout").asIntegerVector().findFirst(); @@ -378,21 +401,19 @@ public abstract class ConnectionFunctions { @Specialization @TruffleBoundary protected RAbstractIntVector socketConnection(String host, int port, boolean server, boolean blocking, String open, - @SuppressWarnings("unused") RAbstractStringVector encoding, int timeout) { + String encoding, int timeout) { try { - if (server) { - return new RSocketConnection(open, true, host, port, blocking, timeout).asVector(); - } else { - return new RSocketConnection(open, false, host, port, blocking, timeout).asVector(); - } + return new RSocketConnection(open, server, host, port, blocking, timeout, encoding).asVector(); } catch (IOException ex) { - throw RError.error(this, RError.Message.CANNOT_OPEN_CONNECTION); + throw error(RError.Message.CANNOT_OPEN_CONNECTION); + } catch (IllegalCharsetNameException ex) { + throw error(RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, ""); } } } @RBuiltin(name = "url", kind = INTERNAL, parameterNames = {"description", "open", "blocking", "encoding", "method"}, behavior = IO) - public abstract static class URLConnection extends RBuiltinNode { + public abstract static class URLConnection extends RBuiltinNode.Arg5 { static { Casts casts = new Casts(URLConnection.class); @@ -405,20 +426,73 @@ public abstract class ConnectionFunctions { @Specialization @TruffleBoundary - protected RAbstractIntVector urlConnection(String url, String open, @SuppressWarnings("unused") boolean blocking, @SuppressWarnings("unused") String encoding, + protected RAbstractIntVector urlConnection(String url, String open, @SuppressWarnings("unused") boolean blocking, String encoding, @SuppressWarnings("unused") String method) { try { - return new URLRConnection(url, open).asVector(); + return new URLRConnection(url, open, encoding).asVector(); } catch (MalformedURLException ex) { - throw RError.error(this, RError.Message.UNSUPPORTED_URL_SCHEME); + throw error(RError.Message.UNSUPPORTED_URL_SCHEME); + } catch (IOException ex) { + throw error(RError.Message.CANNOT_OPEN_CONNECTION); + } catch (IllegalCharsetNameException ex) { + throw error(RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, ""); + } + } + } + + @RBuiltin(name = "rawConnection", kind = INTERNAL, parameterNames = {"description", "object", "open"}, behavior = IO) + public abstract static class RawConnection extends RBuiltinNode.Arg3 { + + static { + Casts casts = new Casts(RawConnection.class); + CastsHelper.description(casts); + casts.arg("object").mustBe(stringValue().or(rawValue())); + CastsHelper.openMode(casts); + } + + @Specialization + @TruffleBoundary + protected RAbstractIntVector rawConnection(String description, @SuppressWarnings("unused") RAbstractStringVector text, String open) { + try { + return new RawRConnection(description, null, open).asVector(); } catch (IOException ex) { - throw RError.error(this, RError.Message.CANNOT_OPEN_CONNECTION); + throw RInternalError.shouldNotReachHere(); + } + } + + @Specialization + @TruffleBoundary + protected RAbstractIntVector rawConnection(String description, RAbstractRawVector text, String open) { + try { + return new RawRConnection(description, text.materialize().getDataTemp(), open).asVector(); + } catch (IOException ex) { + throw RInternalError.shouldNotReachHere(); + } + } + } + + @RBuiltin(name = "rawConnectionValue", kind = INTERNAL, parameterNames = {"con"}, behavior = IO) + public abstract static class RawConnectionValue extends RBuiltinNode.Arg1 { + + static { + Casts casts = new Casts(RawConnectionValue.class); + casts.arg("con").defaultError(Message.NOT_A_RAW_CONNECTION).mustBe(integerValue()).asIntegerVector().findFirst(); + } + + @Specialization + @TruffleBoundary + protected Object textConnection(int con) { + BaseRConnection connection = RConnection.fromIndex(con); + if (connection instanceof RawRConnection) { + return RDataFactory.createRawVector(((RawRConnection) connection).getValue()); + } else { + throw error(Message.NOT_A_RAW_CONNECTION); } } } @RBuiltin(name = "summary.connection", kind = INTERNAL, parameterNames = {"object"}, behavior = IO) - public abstract static class Summary extends RBuiltinNode { + public abstract static class Summary extends RBuiltinNode.Arg1 { private static final RStringVector NAMES = RDataFactory.createStringVector(new String[]{"description", "class", "mode", "text", "opened", "can read", "can write"}, RDataFactory.COMPLETE_VECTOR); @@ -433,7 +507,7 @@ public abstract class ConnectionFunctions { BaseRConnection baseCon = RConnection.fromIndex(object); Object[] data = new Object[NAMES.getLength()]; data[0] = baseCon.getSummaryDescription(); - data[1] = baseCon.getConnectionClass().getPrintName(); + data[1] = baseCon.getConnectionClass(); data[2] = baseCon.getOpenMode().summaryString(); data[3] = baseCon.getSummaryText(); data[4] = baseCon.isOpen() ? "opened" : "closed"; @@ -444,7 +518,7 @@ public abstract class ConnectionFunctions { } @RBuiltin(name = "open", visibility = OFF, kind = INTERNAL, parameterNames = {"con", "open", "blocking"}, behavior = IO) - public abstract static class Open extends RBuiltinNode { + public abstract static class Open extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(Open.class); @@ -459,22 +533,21 @@ public abstract class ConnectionFunctions { try { BaseRConnection baseConn = getBaseConnection(RConnection.fromIndex(con)); if (baseConn.isClosed()) { - throw RError.error(this, RError.Message.INVALID_CONNECTION); + throw error(RError.Message.INVALID_CONNECTION); } if (baseConn.isOpen()) { - RError.warning(this, RError.Message.ALREADY_OPEN_CONNECTION); - return RNull.instance; + warning(RError.Message.ALREADY_OPEN_CONNECTION); } baseConn.open(open); } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); + throw error(RError.Message.GENERIC, ex.getMessage()); } return RNull.instance; } } @RBuiltin(name = "isOpen", kind = INTERNAL, parameterNames = {"con", "rw"}, behavior = IO) - public abstract static class IsOpen extends RBuiltinNode { + public abstract static class IsOpen extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(IsOpen.class); @@ -497,14 +570,14 @@ public abstract class ConnectionFunctions { result &= baseCon.canWrite(); break; default: - throw RError.error(this, RError.Message.UNKNOWN_VALUE, "rw"); + throw error(RError.Message.UNKNOWN_VALUE, "rw"); } return RDataFactory.createLogicalVectorFromScalar(result); } } @RBuiltin(name = "close", visibility = OFF, kind = INTERNAL, parameterNames = {"con", "type"}, behavior = IO) - public abstract static class Close extends RBuiltinNode { + public abstract static class Close extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(Close.class); @@ -519,43 +592,43 @@ public abstract class ConnectionFunctions { try { connection.closeAndDestroy(); } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); + throw error(RError.Message.GENERIC, ex.getMessage()); } return RNull.instance; } } @RBuiltin(name = "readLines", kind = INTERNAL, parameterNames = {"con", "n", "ok", "warn", "encoding", "skipNul"}, behavior = IO) - public abstract static class ReadLines extends RBuiltinNode { + public abstract static class ReadLines extends RBuiltinNode.Arg6 { static { Casts casts = new Casts(ReadLines.class); CastsHelper.connection(casts); - casts.arg("n").asIntegerVector().findFirst().notNA(); - casts.arg("ok").asLogicalVector().findFirst().notNA().map(toBoolean()); - casts.arg("warn").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("n").asIntegerVector().findFirst().mustNotBeNA(); + casts.arg("ok").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); + casts.arg("warn").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); CastsHelper.encoding(casts); - casts.arg("skipNul").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("skipNul").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } @Specialization @TruffleBoundary protected Object readLines(int con, int n, boolean ok, boolean warn, @SuppressWarnings("unused") String encoding, boolean skipNul) { - // TODO implement all the arguments + // TODO Implement argument 'encoding'. try (RConnection openConn = RConnection.fromIndex(con).forceOpen("rt")) { String[] lines = openConn.readLines(n, warn, skipNul); if (n > 0 && lines.length < n && !ok) { - throw RError.error(this, RError.Message.TOO_FEW_LINES_READ_LINES); + throw error(RError.Message.TOO_FEW_LINES_READ_LINES); } return RDataFactory.createStringVector(lines, RDataFactory.COMPLETE_VECTOR); } catch (IOException x) { - throw RError.error(this, RError.Message.ERROR_READING_CONNECTION, x.getMessage()); + throw error(RError.Message.ERROR_READING_CONNECTION, x.getMessage()); } } } @RBuiltin(name = "writeLines", visibility = OFF, kind = INTERNAL, parameterNames = {"text", "con", "sep", "useBytes"}, behavior = IO) - public abstract static class WriteLines extends RBuiltinNode { + public abstract static class WriteLines extends RBuiltinNode.Arg4 { static { Casts casts = new Casts(WriteLines.class); @@ -571,14 +644,14 @@ public abstract class ConnectionFunctions { try (RConnection openConn = RConnection.fromIndex(con).forceOpen("wt")) { openConn.writeLines(text, sep, useBytes); } catch (IOException x) { - throw RError.error(this, RError.Message.ERROR_WRITING_CONNECTION, x.getMessage()); + throw error(RError.Message.ERROR_WRITING_CONNECTION, x.getMessage()); } return RNull.instance; } } @RBuiltin(name = "flush", visibility = OFF, kind = INTERNAL, parameterNames = {"con"}, behavior = IO) - public abstract static class Flush extends RBuiltinNode { + public abstract static class Flush extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(Flush.class); @@ -591,20 +664,20 @@ public abstract class ConnectionFunctions { try { RConnection.fromIndex(con).flush(); } catch (IOException x) { - throw RError.error(this, RError.Message.ERROR_FLUSHING_CONNECTION, x.getMessage()); + throw error(RError.Message.ERROR_FLUSHING_CONNECTION, x.getMessage()); } return RNull.instance; } } @RBuiltin(name = "pushBack", visibility = OFF, kind = INTERNAL, parameterNames = {"data", "con", "newLine", "type"}, behavior = IO) - public abstract static class PushBack extends RBuiltinNode { + public abstract static class PushBack extends RBuiltinNode.Arg4 { static { Casts casts = new Casts(PushBack.class); casts.arg("data").asStringVector().mustBe(instanceOf(RAbstractStringVector.class)); CastsHelper.connection(casts); - casts.arg("newLine").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("newLine").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); casts.arg("type").asIntegerVector().findFirst(); } @@ -617,7 +690,7 @@ public abstract class ConnectionFunctions { } @RBuiltin(name = "pushBackLength", kind = INTERNAL, parameterNames = {"con"}, behavior = IO) - public abstract static class PushBackLength extends RBuiltinNode { + public abstract static class PushBackLength extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(PushBackLength.class); @@ -631,7 +704,7 @@ public abstract class ConnectionFunctions { } @RBuiltin(name = "clearPushBack", visibility = OFF, kind = INTERNAL, parameterNames = {"con"}, behavior = IO) - public abstract static class PushBackClear extends RBuiltinNode { + public abstract static class PushBackClear extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(PushBackClear.class); @@ -646,7 +719,7 @@ public abstract class ConnectionFunctions { } @RBuiltin(name = "readChar", kind = INTERNAL, parameterNames = {"con", "nchars", "useBytes"}, behavior = IO) - public abstract static class ReadChar extends RBuiltinNode { + public abstract static class ReadChar extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(ReadChar.class); @@ -664,14 +737,14 @@ public abstract class ConnectionFunctions { @Specialization(guards = "!ncharsEmpty(nchars)") @TruffleBoundary protected RStringVector readChar(int con, RAbstractIntVector nchars, boolean useBytes) { - try (RConnection openConn = RConnection.fromIndex(con).forceOpen("rb")) { + try (BaseRConnection openConn = RConnection.fromIndex(con).forceOpen("rb")) { String[] data = new String[nchars.getLength()]; for (int i = 0; i < data.length; i++) { data[i] = openConn.readChar(nchars.getDataAt(i), useBytes); } return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR); } catch (IOException x) { - throw RError.error(this, RError.Message.ERROR_READING_CONNECTION, x.getMessage()); + throw error(RError.Message.ERROR_READING_CONNECTION, x.getMessage()); } } @@ -681,43 +754,57 @@ public abstract class ConnectionFunctions { } @RBuiltin(name = "writeChar", visibility = OFF, kind = INTERNAL, parameterNames = {"object", "con", "nchars", "sep", "useBytes"}, behavior = IO) - public abstract static class WriteChar extends RBuiltinNode { + public abstract static class WriteChar extends RBuiltinNode.Arg5 { static { + // @formatter:off Casts casts = new Casts(WriteChar.class); - casts.arg("object").asStringVector(); - casts.arg("con").defaultError(Message.INVALID_CONNECTION).mustBe(integerValue().or(rawValue())).mapIf(integerValue(), - asIntegerVector().setNext(findFirst().integerElement())); + casts.arg("object").mustBe(stringValue(), Message.ONLY_WRITE_CHAR_OBJECTS).asStringVector(); + casts.arg("con").mustBe(rawValue().not(), Message.GENERIC, "raw connection in writeChar not implemented in FastR yet."). + mustBe(stringValue().not(), Message.GENERIC, "filename as a connection in writeChar not implemented in FastR yet."). + mustBe(integerValue(), Message.INVALID_CONNECTION).asIntegerVector().findFirst(); CastsHelper.nchars(casts); - casts.arg("sep").allowNull().mustBe(stringValue()); + casts.arg("sep").mustNotBeMissing().returnIf(nullValue()).mustBe(stringValue()).asStringVector(); CastsHelper.useBytes(casts); + // @formatter:on } - @TruffleBoundary @Specialization protected RNull writeChar(RAbstractStringVector object, int con, RAbstractIntVector nchars, RAbstractStringVector sep, boolean useBytes) { + return writeCharGeneric(object, con, nchars, sep, useBytes); + } + + @TruffleBoundary + private RNull writeCharGeneric(RAbstractStringVector object, int con, RAbstractIntVector nchars, RAbstractStringVector sep, boolean useBytes) { try (RConnection openConn = RConnection.fromIndex(con).forceOpen("wb")) { - int length = object.getLength(); + final int length = object.getLength(); + final int ncharsLen = nchars.getLength(); for (int i = 0; i < length; i++) { + int nc = nchars.getDataAt(i % ncharsLen); String s = object.getDataAt(i); - int nc = nchars.getDataAt(i % length); + final int writeLen = Math.min(s.length(), nc); int pad = nc - s.length(); if (pad > 0) { - RError.warning(this, RError.Message.MORE_CHARACTERS); + warning(RError.Message.MORE_CHARACTERS); } - openConn.writeChar(s, pad, sep.getDataAt(i % length), useBytes); + openConn.writeChar(s.substring(0, writeLen), pad, getSepFor(sep, i), useBytes); } } catch (IOException x) { - throw RError.error(this, RError.Message.ERROR_WRITING_CONNECTION, x.getMessage()); + throw error(RError.Message.ERROR_WRITING_CONNECTION, x.getMessage()); } return RNull.instance; } - @SuppressWarnings("unused") - @TruffleBoundary + private static String getSepFor(RAbstractStringVector sep, int i) { + if (sep != null) { + return sep.getDataAt(i % sep.getLength()); + } + return null; + } + @Specialization - protected RNull writeChar(RAbstractStringVector object, int con, RAbstractIntVector nchars, RNull sep, boolean useBytes) { - throw RError.nyi(this, "writeChar(sep=NULL)"); + protected RNull writeChar(RAbstractStringVector object, int con, RAbstractIntVector nchars, @SuppressWarnings("unused") RNull sep, boolean useBytes) { + return writeCharGeneric(object, con, nchars, null, useBytes); } } @@ -736,7 +823,7 @@ public abstract class ConnectionFunctions { } @RBuiltin(name = "readBin", kind = INTERNAL, parameterNames = {"con", "what", "n", "size", "signed", "swap"}, behavior = IO) - public abstract static class ReadBin extends RBuiltinNode { + public abstract static class ReadBin extends RBuiltinNode.Arg6 { static { Casts casts = new Casts(ReadBin.class); @@ -745,29 +832,30 @@ public abstract class ConnectionFunctions { casts.arg("what").asStringVector().findFirst(); CastsHelper.n(casts); CastsHelper.size(casts); - casts.arg("signed").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("signed").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); CastsHelper.swap(casts); } @Specialization @TruffleBoundary - protected Object readBin(int con, String what, int n, int size, boolean signed, boolean swap) { - RVector<?> result = null; + protected Object readBin(int con, String what, int n, int sizeInput, boolean signed, boolean swap) { + RVector<?> result; BaseRConnection connection = RConnection.fromIndex(con); try (RConnection openConn = connection.forceOpen("rb")) { if (getBaseConnection(openConn).getOpenMode().isText()) { - throw RError.error(this, RError.Message.ONLY_READ_BINARY_CONNECTION); + throw error(RError.Message.ONLY_READ_BINARY_CONNECTION); } switch (what) { case "int": case "integer": + int size = sizeInput; if (size == RRuntime.INT_NA) { size = 4; } - if (size == 1 || size == 4) { + if (size == 1 || size == 4 || size == 2) { result = readInteger(connection, n, size, swap, signed); } else { - throw RError.nyi(this, "readBin \"int\" size not implemented"); + throw RError.nyi(RError.SHOW_CALLER, "readBin \"int\" size not implemented"); } break; case "double": @@ -790,7 +878,7 @@ public abstract class ConnectionFunctions { throw RInternalError.shouldNotReachHere(); } } catch (IOException x) { - throw RError.error(this, RError.Message.ERROR_READING_CONNECTION, x.getMessage()); + throw error(RError.Message.ERROR_READING_CONNECTION, x.getMessage()); } return result; } @@ -821,6 +909,11 @@ public abstract class ConnectionFunctions { int d = signed ? b : b & 0xFF; data[i] = d; } + } else if (size == 2) { + ShortBuffer shortBuffer = buffer.asShortBuffer(); + for (int i = 0; i < nInts; i++) { + data[i] = shortBuffer.get(); + } } return RDataFactory.createIntVector(data, complete); } @@ -874,7 +967,7 @@ public abstract class ConnectionFunctions { int s = 0; while (s < n) { byte[] chars = con.readBinChars(); - if (chars == null) { + if (chars == null || chars.length == 0) { break; } int npos = 0; @@ -1022,12 +1115,11 @@ public abstract class ConnectionFunctions { } @RBuiltin(name = "writeBin", visibility = OFF, kind = INTERNAL, parameterNames = {"object", "con", "size", "swap", "useBytes"}, behavior = IO) - public abstract static class WriteBin extends RBuiltinNode { + public abstract static class WriteBin extends RBuiltinNode.Arg5 { static { Casts casts = new Casts(WriteBin.class); - // TODO atomic, i.e. not RList or RExpression - casts.arg("object").asVector().mustBe(instanceOf(RAbstractVector.class)); + casts.arg("object").asVector().mustBe(RAbstractAtomicVector.class); casts.arg("con").defaultError(Message.INVALID_CONNECTION).mustBe(integerValue().or(rawValue())).mapIf(integerValue(), asIntegerVector().setNext(findFirst().integerElement())); CastsHelper.size(casts); CastsHelper.swap(casts); @@ -1039,29 +1131,27 @@ public abstract class ConnectionFunctions { protected Object writeBin(RAbstractVector object, int con, int size, boolean swap, boolean useBytes, @Cached("create()") WriteDataNode writeData) { if (object instanceof RList || object instanceof RExpression) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "object"); + throw error(RError.Message.INVALID_ARGUMENT, "object"); } if (object.getLength() > 0) { RConnection connection = RConnection.fromIndex(con); try (RConnection openConn = connection.forceOpen("wb")) { if (getBaseConnection(openConn).isTextMode()) { - throw RError.error(this, RError.Message.ONLY_WRITE_BINARY_CONNECTION); + throw error(RError.Message.ONLY_WRITE_BINARY_CONNECTION); } ByteBuffer buffer = writeData.execute(object, size, swap, useBytes); buffer.flip(); connection.writeBin(buffer); } catch (IOException x) { - throw RError.error(this, RError.Message.ERROR_WRITING_CONNECTION, x.getMessage()); + throw error(RError.Message.ERROR_WRITING_CONNECTION, x.getMessage()); } } return RNull.instance; } @Specialization - protected RRawVector writeBin(RAbstractVector object, @SuppressWarnings("unused") RAbstractRawVector con, int size, byte swapArg, byte useBytesArg, + protected RRawVector writeBin(RAbstractVector object, @SuppressWarnings("unused") RAbstractRawVector con, int size, boolean swap, boolean useBytes, @Cached("create()") WriteDataNode writeData) { - boolean swap = RRuntime.fromLogical(swapArg); - boolean useBytes = RRuntime.fromLogical(useBytesArg); ByteBuffer buffer = writeData.execute(object, size, swap, useBytes); buffer.flip(); return RDataFactory.createRawVector(buffer.array()); @@ -1069,7 +1159,7 @@ public abstract class ConnectionFunctions { } @RBuiltin(name = "getConnection", kind = INTERNAL, parameterNames = {"what"}, behavior = IO) - public abstract static class GetConnection extends RBuiltinNode { + public abstract static class GetConnection extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(GetConnection.class); @@ -1081,7 +1171,7 @@ public abstract class ConnectionFunctions { protected RAbstractIntVector getConnection(int what) { BaseRConnection con = RContext.getInstance().stateRConnection.getConnection(what, false); if (con == null) { - throw RError.error(this, RError.Message.NO_SUCH_CONNECTION, what); + throw error(RError.Message.NO_SUCH_CONNECTION, what); } else { return con.asVector(); } @@ -1089,7 +1179,7 @@ public abstract class ConnectionFunctions { } @RBuiltin(name = "getAllConnections", kind = INTERNAL, parameterNames = {}, behavior = IO) - public abstract static class GetAllConnections extends RBuiltinNode { + public abstract static class GetAllConnections extends RBuiltinNode.Arg0 { @Specialization @TruffleBoundary protected RAbstractIntVector getAllConnections() { @@ -1098,7 +1188,7 @@ public abstract class ConnectionFunctions { } @RBuiltin(name = "isSeekable", kind = INTERNAL, parameterNames = "con", behavior = IO) - public abstract static class IsSeekable extends RBuiltinNode { + public abstract static class IsSeekable extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(IsSeekable.class); @@ -1113,7 +1203,7 @@ public abstract class ConnectionFunctions { } @RBuiltin(name = "seek", kind = INTERNAL, parameterNames = {"con", "where", "origin", "rw"}, behavior = IO) - public abstract static class Seek extends RBuiltinNode { + public abstract static class Seek extends RBuiltinNode.Arg4 { static { Casts casts = new Casts(Seek.class); @@ -1131,19 +1221,144 @@ public abstract class ConnectionFunctions { * for the NA (enquiry) case. */ long offset = 0; + final int actualOrigin; if (RRuntime.isNAorNaN(where)) { - origin = 0; + actualOrigin = 0; } else { offset = (long) where; + actualOrigin = origin; } try { - long newOffset = RConnection.fromIndex(con).seek(offset, RConnection.SeekMode.values()[origin], RConnection.SeekRWMode.values()[rw]); + long newOffset = RConnection.fromIndex(con).seek(offset, RConnection.SeekMode.values()[actualOrigin], RConnection.SeekRWMode.values()[rw]); if (newOffset > Integer.MAX_VALUE) { - throw RError.nyi(this, "seek > Integer.MAX_VALUE"); + throw RError.nyi(RError.SHOW_CALLER, "seek > Integer.MAX_VALUE"); } return (int) newOffset; } catch (IOException x) { - throw RError.error(this, RError.Message.GENERIC, x.getMessage()); + throw error(RError.Message.GENERIC, x.getMessage()); + } + } + } + + @RBuiltin(name = "fifo", kind = INTERNAL, parameterNames = {"description", "open", "blocking", "encoding"}, behavior = IO) + public abstract static class Fifo extends RBuiltinNode.Arg4 { + + static { + Casts casts = new Casts(Fifo.class); + CastsHelper.description(casts); + CastsHelper.open(casts); + // We cannot support non-blocking because Java does simply not allow to open a file or + // named pipe in non-blocking mode. + CastsHelper.blockingNotSupported(casts); + CastsHelper.encoding(casts); + } + + @Specialization + @TruffleBoundary + protected RAbstractIntVector fifo(String path, String openArg, boolean blocking, String encoding) { + + String open = openArg; + try { + return new FifoRConnection(path, open, blocking, encoding).asVector(); + } catch (IOException ex) { + warning(RError.Message.CANNOT_OPEN_FIFO, path); + throw error(RError.Message.CANNOT_OPEN_CONNECTION); + } catch (IllegalCharsetNameException ex) { + throw error(RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, ""); + } + } + } + + @RBuiltin(name = "pipe", kind = INTERNAL, parameterNames = {"description", "open", "encoding"}, behavior = IO) + public abstract static class Pipe extends RBuiltinNode.Arg3 { + + static { + Casts casts = new Casts(Pipe.class); + CastsHelper.description(casts); + CastsHelper.open(casts); + CastsHelper.encoding(casts); + } + + @Specialization + @TruffleBoundary + protected RAbstractIntVector pipe(String path, String openArg, String encoding) { + + String open = openArg; + try { + return new PipeRConnection(path, open, encoding).asVector(); + } catch (IOException ex) { + warning(RError.Message.CANNOT_OPEN_FIFO, path); + throw error(RError.Message.CANNOT_OPEN_CONNECTION); + } catch (IllegalCharsetNameException ex) { + throw error(RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, ""); + } + } + } + + @RBuiltin(name = "isIncomplete", kind = INTERNAL, parameterNames = {"con"}, behavior = IO) + public abstract static class IsIncomplete extends RBuiltinNode.Arg1 { + + static { + Casts casts = new Casts(IsIncomplete.class); + CastsHelper.connection(casts); + } + + @Specialization + @TruffleBoundary + protected RLogicalVector isIncomplete(int con) { + + final boolean res = RConnection.fromIndex(con).isIncomplete(); + return RDataFactory.createLogicalVectorFromScalar(res); + } + } + + @RBuiltin(name = "truncate", kind = INTERNAL, parameterNames = {"con"}, behavior = IO) + public abstract static class Truncate extends RBuiltinNode.Arg1 { + + static { + Casts casts = new Casts(Truncate.class); + CastsHelper.connection(casts); + } + + @Specialization + @TruffleBoundary + protected RNull truncate(int con) { + + try { + RConnection.fromIndex(con).truncate(); + } catch (IOException e) { + throw error(RError.Message.TRUNCATE_UNSUPPORTED_FOR_CONN, e.getMessage()); + } + return RNull.instance; + } + } + + @RBuiltin(name = ".fastr.channelConnection", kind = RBuiltinKind.PRIMITIVE, parameterNames = {"channel", "open", "encoding"}, behavior = IO) + public abstract static class ChannelConnection extends RBuiltinNode.Arg3 { + + static { + Casts casts = new Casts(ChannelConnection.class); + casts.arg("channel").mustNotBeMissing().mustBe(nullValue().not().and(instanceOf(TruffleObject.class))); + CastsHelper.openMode(casts); + CastsHelper.encoding(casts); + } + + @Override + public Object[] getDefaultParameterValues() { + return new Object[]{RMissing.instance, RMissing.instance, Charset.defaultCharset().name()}; + } + + @Specialization + @TruffleBoundary + protected RAbstractIntVector channelConnection(TruffleObject channel, String open, String encoding) { + try { + if (JavaInterop.isJavaObject(ByteChannel.class, channel)) { + ByteChannel ch = JavaInterop.asJavaObject(ByteChannel.class, channel); + return new ChannelRConnection("", ch, open, encoding).asVector(); + } + throw error(RError.Message.INVALID_CHANNEL_OBJECT); + } catch (IOException ex) { + throw RInternalError.shouldNotReachHere(); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Contributors.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Contributors.java index 36d37e55470772d8bb70407f72db85070b568ad5..bb5c8b3413621ec937669ee560ec014b0b8d7eba 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Contributors.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Contributors.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 @@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.conn.StdConnections; import com.oracle.truffle.r.runtime.data.RNull; @RBuiltin(name = "contributors", visibility = OFF, kind = SUBSTITUTE, parameterNames = {}, behavior = IO) -public abstract class Contributors extends RBuiltinNode { +public abstract class Contributors extends RBuiltinNode.Arg0 { private static final String CONTRIBUTORS = Utils.getResourceAsString(Contributors.class, "CONTRIBUTORS", true); @@ -48,7 +48,7 @@ public abstract class Contributors extends RBuiltinNode { try { StdConnections.getStdout().writeString(CONTRIBUTORS, true); } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); + throw error(RError.Message.GENERIC, ex.getMessage()); } return RNull.instance; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CopyDFAttr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CopyDFAttr.java index d9f2875e1ccb591a09aae6c1cad02f67cb05d411..e3080d28c883bfb42d704b2c7a3ef5ab1f3346b6 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CopyDFAttr.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CopyDFAttr.java @@ -34,7 +34,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "copyDFattr", kind = INTERNAL, parameterNames = {"", ""}, behavior = COMPLEX) -public abstract class CopyDFAttr extends RBuiltinNode { +public abstract class CopyDFAttr extends RBuiltinNode.Arg2 { static { Casts.noCasts(CopyDFAttr.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java index 842176d6551cdf07ca9ad504d101c6bb22b1757f..56ddfda61520b9138b849c9a25584ee683956452 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java @@ -31,8 +31,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode; -import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode; -import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -42,15 +40,15 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "crossprod", kind = INTERNAL, parameterNames = {"x", "y"}, behavior = PURE) -public abstract class Crossprod extends RBuiltinNode { +public abstract class Crossprod extends RBuiltinNode.Arg2 { @Child private MatMult matMult = MatMultNodeGen.create(/* promoteDimNames: */ false); @Child private Transpose transpose; static { Casts casts = new Casts(Crossprod.class); - casts.arg("x").mustBe(numericValue().or(complexValue()), RError.ROOTNODE, RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR); - casts.arg("y").defaultError(RError.ROOTNODE, RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR).allowNull().mustBe(numericValue().or(complexValue())); + casts.arg("x").mustBe(numericValue().or(complexValue()), RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR); + casts.arg("y").defaultError(RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR).allowNull().mustBe(numericValue().or(complexValue())); } private Object matMult(Object op1, Object op2) { @@ -68,17 +66,14 @@ public abstract class Crossprod extends RBuiltinNode { @Specialization(guards = {"x.isMatrix()", "y.isMatrix()"}) protected RDoubleVector crossprod(RAbstractDoubleVector x, RAbstractDoubleVector y, @Cached("create()") GetDimAttributeNode getXDimsNode, - @Cached("create()") GetDimAttributeNode getYDimsNode, - @Cached("create()") SetDimNamesAttributeNode setDimNamesNode, - @Cached("create()") GetDimNamesAttributeNode getADimNamesNode, - @Cached("create()") GetDimNamesAttributeNode getBDimNamesNode) { + @Cached("create()") GetDimAttributeNode getYDimsNode) { int[] xDims = getXDimsNode.getDimensions(x); int[] yDims = getYDimsNode.getDimensions(y); int xRows = xDims[0]; int xCols = xDims[1]; int yRows = yDims[0]; int yCols = yDims[1]; - return matMult.doubleMatrixMultiply(x, y, xCols, xRows, yRows, yCols, xRows, 1, 1, yRows, false, setDimNamesNode, getADimNamesNode, getBDimNamesNode); + return matMult.doubleMatrixMultiply(x, y, xCols, xRows, yRows, yCols, xRows, 1, 1, yRows, false); } private static RDoubleVector mirror(RDoubleVector result, GetDimAttributeNode getResultDimsNode) { @@ -110,14 +105,11 @@ public abstract class Crossprod extends RBuiltinNode { @Specialization(guards = "x.isMatrix()") protected RDoubleVector crossprodDoubleMatrix(RAbstractDoubleVector x, @SuppressWarnings("unused") RNull y, @Cached("create()") GetDimAttributeNode getDimsNode, - @Cached("create()") GetDimAttributeNode getResultDimsNode, - @Cached("create()") SetDimNamesAttributeNode setDimNamesNode, - @Cached("create()") GetDimNamesAttributeNode getADimNamesNode, - @Cached("create()") GetDimNamesAttributeNode getBDimNamesNode) { + @Cached("create()") GetDimAttributeNode getResultDimsNode) { int[] xDims = getDimsNode.getDimensions(x); int xRows = xDims[0]; int xCols = xDims[1]; - return mirror(matMult.doubleMatrixMultiply(x, x, xCols, xRows, xRows, xCols, xRows, 1, 1, xRows, true, setDimNamesNode, getADimNamesNode, getBDimNamesNode), getResultDimsNode); + return mirror(matMult.doubleMatrixMultiply(x, x, xCols, xRows, xRows, xCols, xRows, 1, 1, xRows, true), getResultDimsNode); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMax.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMax.java index 236988ed4697a42c9593a61552bdb30ff7c32f3d..b21e15c0bcfccc12fd6186f06637d87390850e3c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMax.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMax.java @@ -15,6 +15,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asIntegerVec import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; import static com.oracle.truffle.r.runtime.RDispatch.MATH_GROUP_GENERIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -34,22 +35,21 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RIntSequence; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "cummax", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) -public abstract class CumMax extends RBuiltinNode { +public abstract class CumMax extends RBuiltinNode.Arg1 { private final NACheck na = NACheck.create(); @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create(); static { Casts casts = new Casts(CumMax.class); - casts.arg("x").allowNull().mustBe(complexValue().not(), RError.Message.CUMMAX_UNDEFINED_FOR_COMPLEX).mapIf(integerValue().or(logicalValue()), asIntegerVector(true, false, false), - asDoubleVector(true, false, false)); + casts.arg("x").allowNull().mustBe(missingValue().not(), RError.Message.ARGUMENT_EMPTY, 0, "cumsum", 1).mustBe(complexValue().not(), RError.Message.CUMMAX_UNDEFINED_FOR_COMPLEX).mapIf( + integerValue().or(logicalValue()), asIntegerVector(true, false, false), asDoubleVector(true, false, false)); } @Specialization @@ -67,11 +67,6 @@ public abstract class CumMax extends RBuiltinNode { return RDataFactory.createEmptyDoubleVector(); } - @Specialization(guards = "emptyVec.getLength()==0") - protected RAbstractVector cumEmpty(RAbstractComplexVector emptyVec) { - return RDataFactory.createComplexVector(new double[0], true, emptyVec.getNames()); - } - @Specialization(guards = "emptyVec.getLength()==0") protected RAbstractVector cumEmpty(RAbstractDoubleVector emptyVec) { return RDataFactory.createDoubleVector(new double[0], true, emptyVec.getNames()); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMin.java index ae28196a601f003886b7738af55b3c9bfe41a2a1..c558b2df55593104dfa129c01f52fedb1118e3a6 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMin.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMin.java @@ -15,6 +15,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asIntegerVec import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; import static com.oracle.truffle.r.runtime.RDispatch.MATH_GROUP_GENERIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -34,22 +35,21 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RIntSequence; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "cummin", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) -public abstract class CumMin extends RBuiltinNode { +public abstract class CumMin extends RBuiltinNode.Arg1 { private final NACheck na = NACheck.create(); @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create(); static { Casts casts = new Casts(CumMin.class); - casts.arg("x").allowNull().mustBe(complexValue().not(), RError.Message.CUMMIN_UNDEFINED_FOR_COMPLEX).mapIf(integerValue().or(logicalValue()), asIntegerVector(true, false, false), - asDoubleVector(true, false, false)); + casts.arg("x").allowNull().mustBe(missingValue().not(), RError.Message.ARGUMENT_EMPTY, 0, "cumsum", 1).mustBe(complexValue().not(), RError.Message.CUMMIN_UNDEFINED_FOR_COMPLEX).mapIf( + integerValue().or(logicalValue()), asIntegerVector(true, false, false), asDoubleVector(true, false, false)); } @Specialization @@ -67,11 +67,6 @@ public abstract class CumMin extends RBuiltinNode { return RDataFactory.createEmptyDoubleVector(); } - @Specialization(guards = "emptyVec.getLength()==0") - protected RAbstractVector cumEmpty(RAbstractComplexVector emptyVec) { - return RDataFactory.createComplexVector(new double[0], true, emptyVec.getNames()); - } - @Specialization(guards = "emptyVec.getLength()==0") protected RAbstractVector cumEmpty(RAbstractDoubleVector emptyVec) { return RDataFactory.createDoubleVector(new double[0], true, emptyVec.getNames()); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumProd.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumProd.java index ef609bb01119c116b02ced24964414134ca960ac..69767d4e3dd9bf4cd91cdf9c527a677e1d101a19 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumProd.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumProd.java @@ -12,6 +12,7 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asDoubleVector; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; import static com.oracle.truffle.r.runtime.RDispatch.MATH_GROUP_GENERIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -21,6 +22,7 @@ import java.util.Arrays; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RComplex; @@ -35,7 +37,7 @@ import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "cumprod", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) -public abstract class CumProd extends RBuiltinNode { +public abstract class CumProd extends RBuiltinNode.Arg1 { private final NACheck na = NACheck.create(); @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create(); @@ -44,12 +46,7 @@ public abstract class CumProd extends RBuiltinNode { static { Casts casts = new Casts(CumProd.class); - casts.arg("x").allowNull().mapIf(complexValue().not(), asDoubleVector(true, false, false)); - } - - @Specialization - protected int cumprod(int arg) { - return arg; + casts.arg("x").allowNull().mustBe(missingValue().not(), RError.Message.ARGUMENT_EMPTY, 0, "cumsum", 1).mapIf(complexValue().not(), asDoubleVector(true, false, false)); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumSum.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumSum.java index 7a1886ac6ee122a9b987e4959dada87ca123bcfa..683d2b46ad780a6b3ca3e1e7e2d6035ac4ca1ba8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumSum.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumSum.java @@ -29,6 +29,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.mapIf; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; import static com.oracle.truffle.r.runtime.RDispatch.MATH_GROUP_GENERIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -38,6 +39,7 @@ import java.util.Arrays; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RComplex; @@ -55,7 +57,7 @@ import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "cumsum", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) -public abstract class CumSum extends RBuiltinNode { +public abstract class CumSum extends RBuiltinNode.Arg1 { private final NACheck na = NACheck.create(); @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create(); @@ -64,7 +66,8 @@ public abstract class CumSum extends RBuiltinNode { static { Casts casts = new Casts(CumSum.class); - casts.arg("x").allowNull().mapIf(integerValue().or(logicalValue()), asIntegerVector(true, false, false), chain(mapIf(complexValue().not(), asDoubleVector(true, false, false))).end()); + casts.arg("x").allowNull().mustBe(missingValue().not(), RError.Message.ARGUMENT_EMPTY, 0, "cumsum", 1).mapIf(integerValue().or(logicalValue()), asIntegerVector(true, false, false), + chain(mapIf(complexValue().not(), asDoubleVector(true, false, false))).end()); } @Specialization 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 8a7255109242749be6f443c5dc4f98131ede3bbc..d0361a493fd9fba3da09709a9e967e9334354574 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 @@ -41,7 +41,7 @@ import com.oracle.truffle.r.runtime.conn.RConnection; * The {@code dput .Internal}. */ @RBuiltin(name = "dput", visibility = OFF, kind = INTERNAL, parameterNames = {"x", "file", "opts"}, behavior = IO) -public abstract class DPut extends RBuiltinNode { +public abstract class DPut extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(DPut.class); @@ -56,7 +56,7 @@ public abstract class DPut extends RBuiltinNode { try (RConnection openConn = RConnection.fromIndex(file).forceOpen("wt")) { openConn.writeString(string, true); } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); + throw error(RError.Message.GENERIC, ex.getMessage()); } return x; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Date.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Date.java index 2fc9b6f40b7db921f916333bc7eccc64a093de02..cbf8371eec4c2a499a19820663d0b060724adda7 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Date.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Date.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. */ @@ -23,7 +23,7 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "date", kind = INTERNAL, parameterNames = {}, behavior = IO) -public abstract class Date extends RBuiltinNode { +public abstract class Date extends RBuiltinNode.Arg0 { @Specialization @TruffleBoundary diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java index f5ea8c6b09eca0a406161cac73c4fa708cfb6b22..963a91850bce768380aa729a5abe1be9d79a090d 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java @@ -13,7 +13,9 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleVector; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyStringVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE; @@ -135,13 +137,13 @@ public class DatePOSIXFunctions { } @RBuiltin(name = "Date2POSIXlt", kind = INTERNAL, parameterNames = "x", behavior = PURE) - public abstract static class Date2POSIXlt extends RBuiltinNode { + public abstract static class Date2POSIXlt extends RBuiltinNode.Arg1 { @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create(); static { Casts casts = new Casts(Date2POSIXlt.class); - casts.arg("x").mapNull(emptyDoubleVector()).asDoubleVector(); + casts.arg("x").mustNotBeMissing().mapIf(nullValue(), emptyDoubleVector()).asDoubleVector(); } @Specialization @@ -171,14 +173,14 @@ public class DatePOSIXFunctions { } @RBuiltin(name = "as.POSIXlt", kind = INTERNAL, parameterNames = {"x", "tz"}, behavior = READS_STATE) - public abstract static class AsPOSIXlt extends RBuiltinNode { + public abstract static class AsPOSIXlt extends RBuiltinNode.Arg2 { @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create(); static { Casts casts = new Casts(AsPOSIXlt.class); - casts.arg("x").mapNull(emptyDoubleVector()).asDoubleVector(true, false, false); - casts.arg("tz").asStringVector().findFirst(""); + casts.arg("x").mapNull(emptyDoubleVector()).mustBe(missingValue().not()).asDoubleVector(true, false, false); + casts.arg("tz").mustNotBeMissing().asStringVector().findFirst(""); } @Specialization @@ -213,7 +215,7 @@ public class DatePOSIXFunctions { } @RBuiltin(name = "as.POSIXct", kind = INTERNAL, parameterNames = {"x", "tz"}, behavior = READS_STATE) - public abstract static class AsPOSIXct extends RBuiltinNode { + public abstract static class AsPOSIXct extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(AsPOSIXct.class); @@ -271,7 +273,7 @@ public class DatePOSIXFunctions { } @RBuiltin(name = "POSIXlt2Date", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) - public abstract static class POSIXlt2Date extends RBuiltinNode { + public abstract static class POSIXlt2Date extends RBuiltinNode.Arg1 { private static final RStringVector CLASS_ATTR = (RStringVector) RDataFactory.createStringVectorFromScalar("Date").makeSharedPermanent(); static { @@ -322,7 +324,7 @@ public class DatePOSIXFunctions { } @RBuiltin(name = "format.POSIXlt", kind = INTERNAL, parameterNames = {"x", "format", "usetz"}, behavior = READS_STATE) - public abstract static class FormatPOSIXlt extends RBuiltinNode { + public abstract static class FormatPOSIXlt extends RBuiltinNode.Arg3 { private static final HashMap<String, String> TIME_ZONE_MAPPING = new HashMap<>(); @@ -388,13 +390,13 @@ public class DatePOSIXFunctions { } @RBuiltin(name = "strptime", kind = INTERNAL, parameterNames = {"x", "format", "tz"}, behavior = PURE) - public abstract static class StrPTime extends RBuiltinNode { + public abstract static class StrPTime extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(StrPTime.class); - casts.arg("x").mapNull(emptyStringVector()).asStringVector(); - casts.arg("format").mapNull(emptyStringVector()).asStringVector(); - casts.arg("tz").mapNull(emptyStringVector()).asStringVector(); + casts.arg("x").mapNull(emptyStringVector()).mustBe(missingValue().not()).asStringVector(); + casts.arg("format").mapNull(emptyStringVector()).mustBe(missingValue().not()).asStringVector(); + casts.arg("tz").mapNull(emptyStringVector()).mustBe(missingValue().not()).asStringVector(); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java index c6f3bba7160fdb8272df5c92127563eba3f7166c..e0793ec5a6f9c87c4c6219f5a5909bd74dcb78c1 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java @@ -29,6 +29,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.helpers.DebugHandling; import com.oracle.truffle.r.runtime.RError; @@ -37,29 +38,27 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; public class DebugFunctions { - protected abstract static class ErrorAndFunAdapter extends RBuiltinNode { - - protected static Casts createCasts(Class<? extends ErrorAndFunAdapter> extCls) { - Casts casts = new Casts(extCls); - casts.arg("fun").mustBe(RFunction.class, Message.ARG_MUST_BE_CLOSURE); - return casts; - } + protected static Casts createCasts(Class<? extends RBuiltinNode> extCls) { + Casts casts = new Casts(extCls); + casts.arg("fun").mustBe(RFunction.class, Message.ARG_MUST_BE_CLOSURE); + return casts; + } - protected void doDebug(RFunction fun, Object text, Object condition, boolean once) throws RError { - // GnuR does not generate an error for builtins, but debug (obviously) has no effect - if (!fun.isBuiltin()) { - if (!DebugHandling.enableDebug(fun, text, condition, once, false)) { - throw RError.error(this, RError.Message.GENERIC, "failed to attach debug handler (not instrumented?)"); - } + protected static void doDebug(RBaseNode node, RFunction fun, Object text, Object condition, boolean once) throws RError { + // GnuR does not generate an error for builtins, but debug (obviously) has no effect + if (!fun.isBuiltin()) { + if (!DebugHandling.enableDebug(fun, text, condition, once, false)) { + throw node.error(RError.Message.GENERIC, "failed to attach debug handler (not instrumented?)"); } } } @RBuiltin(name = "debug", visibility = OFF, kind = INTERNAL, parameterNames = {"fun", "text", "condition"}, behavior = COMPLEX) - public abstract static class Debug extends ErrorAndFunAdapter { + public abstract static class Debug extends RBuiltinNode.Arg3 { static { createCasts(Debug.class); @@ -67,14 +66,14 @@ public class DebugFunctions { @Specialization @TruffleBoundary - protected RNull doDebug(RFunction fun, Object text, Object condition) { - doDebug(fun, text, condition, false); + protected RNull debug(RFunction fun, Object text, Object condition) { + doDebug(this, fun, text, condition, false); return RNull.instance; } } @RBuiltin(name = "debugonce", visibility = OFF, kind = INTERNAL, parameterNames = {"fun", "text", "condition"}, behavior = COMPLEX) - public abstract static class DebugOnce extends ErrorAndFunAdapter { + public abstract static class DebugOnce extends RBuiltinNode.Arg3 { static { createCasts(DebugOnce.class); @@ -84,13 +83,13 @@ public class DebugFunctions { @TruffleBoundary protected RNull debugonce(RFunction fun, Object text, Object condition) { // TODO implement - doDebug(fun, text, condition, true); + doDebug(this, fun, text, condition, true); return RNull.instance; } } @RBuiltin(name = "undebug", visibility = OFF, kind = INTERNAL, parameterNames = {"fun"}, behavior = COMPLEX) - public abstract static class UnDebug extends ErrorAndFunAdapter { + public abstract static class UnDebug extends RBuiltinNode.Arg1 { static { createCasts(UnDebug.class); @@ -100,14 +99,14 @@ public class DebugFunctions { @TruffleBoundary protected RNull undebug(RFunction func) { if (!DebugHandling.undebug(func)) { - throw RError.error(this, RError.Message.NOT_DEBUGGED); + throw error(RError.Message.NOT_DEBUGGED); } return RNull.instance; } } @RBuiltin(name = "isdebugged", kind = INTERNAL, parameterNames = {"fun"}, behavior = PURE) - public abstract static class IsDebugged extends ErrorAndFunAdapter { + public abstract static class IsDebugged extends RBuiltinNode.Arg1 { static { createCasts(IsDebugged.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DelayedAssign.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DelayedAssign.java index 6db3144a985f4b5e0db857ba8b6aca1614d50193..d62180268e2533f72a3793fda7ca1a97160fa8ba 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DelayedAssign.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DelayedAssign.java @@ -31,7 +31,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.RASTUtils; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; @@ -44,15 +43,13 @@ import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.env.REnvironment.PutException; @RBuiltin(name = "delayedAssign", visibility = OFF, kind = INTERNAL, parameterNames = {"x", "value", "eval.env", "assign.env"}, behavior = COMPLEX) -public abstract class DelayedAssign extends RBuiltinNode { - - private final BranchProfile errorProfile = BranchProfile.create(); +public abstract class DelayedAssign extends RBuiltinNode.Arg4 { static { Casts casts = new Casts(DelayedAssign.class); casts.arg("x").mustBe(stringValue()).asStringVector().mustBe(notEmpty(), RError.Message.INVALID_FIRST_ARGUMENT).findFirst(); - casts.arg("eval.env").mustNotBeNull(RError.SHOW_CALLER, RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class)); - casts.arg("assign.env").mustNotBeNull(RError.SHOW_CALLER, RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class)); + casts.arg("eval.env").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class)); + casts.arg("assign.env").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class)); } @Specialization @@ -62,8 +59,7 @@ public abstract class DelayedAssign extends RBuiltinNode { assignEnv.put(name, RDataFactory.createPromise(PromiseState.Explicit, Closure.create(RASTUtils.createNodeForValue(value)), evalEnv.getFrame())); return RNull.instance; } catch (PutException ex) { - errorProfile.enter(); - throw RError.error(this, ex); + throw error(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 e1abc2461e3fb24e568e8b3381d71c5469c2585a..fdd7a26615bc8c8b22a40276dca4f24dcdb20cc5 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 @@ -28,7 +28,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector; // Part of this transcribed from GnuR src/main/deparse.c @RBuiltin(name = "deparse", kind = INTERNAL, parameterNames = {"expr", "width.cutoff", "backtick", "control", "nlines"}, behavior = PURE) -public abstract class Deparse extends RBuiltinNode { +public abstract class Deparse extends RBuiltinNode.Arg5 { static { Casts casts = new Casts(Deparse.class); @@ -43,7 +43,7 @@ public abstract class Deparse extends RBuiltinNode { 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) { - RError.warning(this, RError.Message.DEPARSE_INVALID_CUTOFF); + warning(RError.Message.DEPARSE_INVALID_CUTOFF); widthCutoff = RDeparse.DEFAULT_Cutoff; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java index 6ddd7cabaf0a63f137a4dea068a2dfaeadcce128..6d2ba76bcbd4cf034911c7e9525383cdb0ec0837 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java @@ -14,6 +14,7 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asDoubleVector; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte0; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notIntNA; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; @@ -22,7 +23,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -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.builtins.RBuiltin; @@ -34,22 +34,20 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "diag", kind = INTERNAL, parameterNames = {"x", "nrow", "ncol"}, behavior = PURE) -public abstract class Diag extends RBuiltinNode { +public abstract class Diag extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(Diag.class); - casts.arg("x").allowNull().mapIf(complexValue().not(), asDoubleVector()); - + casts.arg("x").mustNotBeMissing().returnIf(nullValue()).mapIf(complexValue().not(), asDoubleVector()); casts.arg("nrow").asIntegerVector().findFirst().mustBe(notIntNA(), Message.INVALID_LARGE_NA_VALUE, "nrow").mustBe(gte0(), Message.INVALID_NEGATIVE_VALUE, "nrow"); - casts.arg("ncol").asIntegerVector().findFirst().mustBe(notIntNA(), Message.INVALID_LARGE_NA_VALUE, "ncol").mustBe(gte0(), Message.INVALID_NEGATIVE_VALUE, "ncol"); } - private static int checkX(RAbstractVector x, int nrow, int ncol) { + private int checkX(RAbstractVector x, int nrow, int ncol) { int mn = (nrow < ncol) ? nrow : ncol; if (mn > 0 && x.getLength() == 0) { CompilerDirectives.transferToInterpreter(); - throw RError.error(RError.SHOW_CALLER2, Message.POSITIVE_LENGTH, "x"); + throw error(Message.POSITIVE_LENGTH, "x"); } return mn; } @@ -59,7 +57,7 @@ public abstract class Diag extends RBuiltinNode { if (nrow == 0 && ncol == 0) { return RDataFactory.createDoubleVector(new double[]{}, true, new int[]{0, 0}); } else { - throw RError.error(RError.SHOW_CALLER2, Message.X_NUMERIC); + throw error(Message.X_NUMERIC); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java index 9e495172e5ddfa9b633c73da7eaff65ecf8fc582..ddc5113be3b33991db30d9ba4f01053a0b68fed8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java @@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; @RBuiltin(name = "dim", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE) -public abstract class Dim extends RBuiltinNode { +public abstract class Dim extends RBuiltinNode.Arg1 { static { Casts.noCasts(Dim.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java index 2993a023e58813ab9b89c0b08244068e5eaf09ad..bcbd242272dbcbce9ae91088c65459cad906e17b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java @@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; @RBuiltin(name = "dimnames", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE) -public abstract class DimNames extends RBuiltinNode { +public abstract class DimNames extends RBuiltinNode.Arg1 { private final ConditionProfile nullProfile = ConditionProfile.createBinaryProfile(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java index 9976ccbaa8c3addfb04bec75e50d1f3757b4eaef..ec10b5b52c2799325428a28f97b2791f025321dd 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java @@ -28,7 +28,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; import static com.oracle.truffle.r.runtime.RVisibility.CUSTOM; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; @@ -36,12 +35,12 @@ import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.RASTUtils; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.GetFunctions.Get; import com.oracle.truffle.r.nodes.builtin.base.GetFunctionsFactory.GetNodeGen; import com.oracle.truffle.r.nodes.function.call.RExplicitCallNode; +import com.oracle.truffle.r.nodes.function.opt.ShareObjectNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; @@ -56,7 +55,6 @@ import com.oracle.truffle.r.runtime.data.REmpty; import com.oracle.truffle.r.runtime.data.RFunction; 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.RPromise; import com.oracle.truffle.r.runtime.data.RPromise.Closure; import com.oracle.truffle.r.runtime.data.RPromise.PromiseState; @@ -68,9 +66,8 @@ import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; -// TODO Implement completely, this is a simple implementation that works when the envir argument is ignored -@RBuiltin(name = "do.call", visibility = CUSTOM, kind = RBuiltinKind.SUBSTITUTE, parameterNames = {"what", "args", "quote", "envir"}, behavior = COMPLEX) -public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNodeChildren { +@RBuiltin(name = ".fastr.do.call", visibility = CUSTOM, kind = RBuiltinKind.INTERNAL, parameterNames = {"what", "args", "quote", "envir"}, behavior = COMPLEX) +public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSyntaxNodeChildren { @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create(); @@ -84,51 +81,25 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode casts.arg("what").defaultError(Message.MUST_BE_STRING_OR_FUNCTION, "what").mustBe(instanceOf(RFunction.class).or(stringValue())); casts.arg("args").mustBe(RAbstractListVector.class, Message.SECOND_ARGUMENT_LIST); casts.arg("quote").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); - casts.arg("envir").allowMissing().mustBe(REnvironment.class, Message.MUST_BE_ENVIRON, "envir"); + casts.arg("envir").mustNotBeMissing().mustBe(REnvironment.class, Message.MUST_BE_ENVIRON, "envir"); } protected static Get createGet() { return GetNodeGen.create(); } - protected ReadVariableNode createRead(RAbstractStringVector what) { - if (what.getLength() != 1) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.MUST_BE_STRING_OR_FUNCTION, "what"); - } - return ReadVariableNode.createForcedFunctionLookup(RSyntaxNode.INTERNAL, what.getDataAt(0)); - } - @Specialization protected Object doCall(VirtualFrame frame, RAbstractStringVector what, RList argsAsList, boolean quote, REnvironment env, @Cached("createGet()") Get getNode) { if (what.getLength() != 1) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.MUST_BE_STRING_OR_FUNCTION, "what"); + throw error(RError.Message.MUST_BE_STRING_OR_FUNCTION, "what"); } RFunction func = (RFunction) getNode.execute(frame, what.getDataAt(0), env, RType.Function.getName(), true); return doCall(frame, func, argsAsList, quote, env); } - @Specialization(limit = "3", guards = {"what.getLength() == 1", "read.getIdentifier() == what.getDataAt(0)"}) - protected Object doCallCached(VirtualFrame frame, @SuppressWarnings("unused") RAbstractStringVector what, RList argsAsList, boolean quote, RMissing env, - @Cached("createRead(what)") ReadVariableNode read) { - RFunction func = (RFunction) read.execute(frame); - return doCall(frame, func, argsAsList, quote, env); - } - - @Specialization(replaces = "doCallCached") - protected Object doCall(VirtualFrame frame, RAbstractStringVector what, RList argsAsList, boolean quote, RMissing env) { - if (what.getLength() != 1) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.MUST_BE_STRING_OR_FUNCTION, "what"); - } - RFunction func = ReadVariableNode.lookupFunction(what.getDataAt(0), frame.materialize()); - return doCall(frame, func, argsAsList, quote, env); - } - @Specialization - protected Object doCall(VirtualFrame frame, RFunction func, RList argsAsList, boolean quote, @SuppressWarnings("unused") Object env) { + protected Object doCall(VirtualFrame frame, RFunction func, RList argsAsList, boolean quote, REnvironment env) { /* * To re-create the illusion of a normal call, turn the values in argsAsList into promises. */ @@ -151,19 +122,28 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode if (arg instanceof RLanguage) { containsRLanguageProfile.enter(); RLanguage lang = (RLanguage) arg; - argValues[i] = createRLanguagePromise(frame.materialize(), lang); + argValues[i] = createRLanguagePromise(env.getFrame().materialize(), lang); } else if (arg instanceof RSymbol) { containsRSymbolProfile.enter(); RSymbol symbol = (RSymbol) arg; if (symbol.getName().isEmpty()) { argValues[i] = REmpty.instance; } else { - argValues[i] = createLookupPromise(frame.materialize(), symbol); + argValues[i] = createLookupPromise(env.getFrame().materialize(), symbol); } } } } - return call.execute(frame, func, new RArgsValuesAndNames(argValues, signature)); + for (int i = 0; i < argValues.length; i++) { + ShareObjectNode.share(argValues[i]); + } + try { + return call.execute(frame, func, new RArgsValuesAndNames(argValues, signature)); + } finally { + for (int i = 0; i < argValues.length; i++) { + ShareObjectNode.unshare(argValues[i]); + } + } } @TruffleBoundary diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Drop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Drop.java index 295782ffeddd39e036218c3ec8828e504f35691d..c326691292d80b7c9e1ca3af7aac3af91323645a 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Drop.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Drop.java @@ -43,7 +43,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "drop", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) -public abstract class Drop extends RBuiltinNode { +public abstract class Drop extends RBuiltinNode.Arg1 { private final ConditionProfile nullDimensions = ConditionProfile.createBinaryProfile(); private final ConditionProfile resultIsVector = ConditionProfile.createBinaryProfile(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java index 79f201063c8527f804895e203f09c65f5b8c32c7..dface54eb35148396b1b38cf1e18f7587b918e4d 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java @@ -16,8 +16,8 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyList; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.binary.CastTypeNode; @@ -32,58 +32,24 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RLogicalVector; import com.oracle.truffle.r.runtime.data.RTypedValue; -import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.nodes.DuplicationHelper; public class DuplicatedFunctions { - protected abstract static class Adapter extends RBuiltinNode { - @Child protected CastTypeNode castTypeNode; - @Child protected TypeofNode typeof; - - private final ConditionProfile incomparable = ConditionProfile.createBinaryProfile(); + @RBuiltin(name = "duplicated", kind = INTERNAL, parameterNames = {"x", "incomparables", "fromLast", "nmax"}, behavior = PURE) + public abstract static class Duplicated extends RBuiltinNode.Arg4 { protected static void casts(Casts casts) { // these are similar to those in DuplicatedFunctions.java - casts.arg("x").mapNull(emptyList()).mustBe(abstractVectorValue(), RError.SHOW_CALLER, - RError.Message.APPLIES_TO_VECTORS, - "duplicated()").asVector(); + casts.arg("x").mapNull(emptyList()).mustBe(abstractVectorValue(), RError.Message.APPLIES_TO_VECTORS, "duplicated()").asVector(); // not much more can be done for incomparables as it is either a vector of incomparable // values or a (single) logical value casts.arg("incomparables").asVector(true); casts.arg("fromLast").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); } - protected boolean isIncomparable(RAbstractVector incomparables) { - if (incomparable.profile(incomparables.getLength() == 1 && incomparables instanceof RLogicalVector && ((RAbstractLogicalVector) incomparables).getDataAt(0) == RRuntime.LOGICAL_FALSE)) { - return false; - } else { - return true; - } - } - - protected boolean notAbstractVector(Object o) { - return !(o instanceof RAbstractVector); - } - - protected boolean empty(RAbstractContainer x) { - return x.getLength() == 0; - } - - protected void initChildren() { - if (castTypeNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castTypeNode = insert(CastTypeNodeGen.create(null, null)); - typeof = insert(TypeofNodeGen.create()); - } - } - } - - @RBuiltin(name = "duplicated", kind = INTERNAL, parameterNames = {"x", "incomparables", "fromLast", "nmax"}, behavior = PURE) - public abstract static class Duplicated extends Adapter { - static { Casts casts = new Casts(Duplicated.class); casts(casts); @@ -92,74 +58,111 @@ public class DuplicatedFunctions { casts.arg("nmax").asIntegerVector().findFirst(RRuntime.INT_NA); } + private final ConditionProfile incomparable = ConditionProfile.createBinaryProfile(); + + protected boolean isIncomparable(RAbstractVector incomparables) { + if (incomparable.profile(incomparables.getLength() == 1 && incomparables instanceof RLogicalVector && ((RAbstractLogicalVector) incomparables).getDataAt(0) == RRuntime.LOGICAL_FALSE)) { + return false; + } else { + return true; + } + } + @TruffleBoundary protected static RLogicalVector analyzeAndCreateResult(RAbstractVector x, RAbstractVector incomparables, byte fromLast) { DuplicationHelper ds = DuplicationHelper.analyze(x, incomparables, false, RRuntime.fromLogical(fromLast)); return RDataFactory.createLogicalVector(ds.getDupVec(), RDataFactory.COMPLETE_VECTOR); } - @Specialization(guards = {"!isIncomparable(incomparables)", "!empty(x)"}) + @Specialization(guards = {"!isIncomparable(incomparables)", "x.getLength() != 0"}) protected RLogicalVector duplicatedFalseIncomparables(RAbstractVector x, @SuppressWarnings("unused") RAbstractVector incomparables, byte fromLast, @SuppressWarnings("unused") int nmax) { return analyzeAndCreateResult(x, null, fromLast); } - @Specialization(guards = {"isIncomparable(incomparables)", "!empty(x)"}) - protected RLogicalVector duplicatedTrueIncomparables(RAbstractVector x, RAbstractVector incomparables, byte fromLast, @SuppressWarnings("unused") int nmax) { - initChildren(); + protected static TypeofNode createTypeof() { + return TypeofNodeGen.create(); + } + + protected static CastTypeNode createCastType() { + return CastTypeNodeGen.create(); + } + + @Specialization(guards = {"isIncomparable(incomparables)", "x.getLength() != 0"}) + protected RLogicalVector duplicatedTrueIncomparables(RAbstractVector x, RAbstractVector incomparables, byte fromLast, @SuppressWarnings("unused") int nmax, + @Cached("createTypeof()") TypeofNode typeof, + @Cached("createCastType()") CastTypeNode castTypeNode) { RType xType = typeof.execute(x); RAbstractVector vector = (RAbstractVector) (castTypeNode.execute(incomparables, xType)); return analyzeAndCreateResult(x, vector, fromLast); } @SuppressWarnings("unused") - @Specialization(guards = {"notAbstractVector(incomparables)", "!empty(x)"}) - protected RLogicalVector duplicatedTrueIncomparables(RAbstractVector x, Object incomparables, byte fromLast, int nmax) { - initChildren(); + @Specialization(guards = {"!isRAbstractVector(incomparables)", "x.getLength() != 0"}) + protected RLogicalVector duplicatedTrueIncomparables(RAbstractVector x, Object incomparables, byte fromLast, int nmax, + @Cached("createTypeof()") TypeofNode typeof) { RType xType = typeof.execute(x); // TODO: this is not quite correct, as passing expression generated some obscure error // message, but is it worth fixing - throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_COERCE, ((RTypedValue) incomparables).getRType().getName(), xType.getName()); + throw error(RError.Message.CANNOT_COERCE, ((RTypedValue) incomparables).getRType().getName(), xType.getName()); } @SuppressWarnings("unused") - @Specialization(guards = "empty(x)") + @Specialization(guards = "x.getLength() == 0") protected RLogicalVector duplicatedEmpty(RAbstractVector x, Object incomparables, byte fromLast, int nmax) { return RDataFactory.createEmptyLogicalVector(); } } @RBuiltin(name = "anyDuplicated", kind = INTERNAL, parameterNames = {"x", "incomparables", "fromLast"}, behavior = PURE) - public abstract static class AnyDuplicated extends Adapter { + public abstract static class AnyDuplicated extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(AnyDuplicated.class); - casts(casts); + Duplicated.casts(casts); + } + + private final ConditionProfile incomparable = ConditionProfile.createBinaryProfile(); + + protected boolean isIncomparable(RAbstractVector incomparables) { + if (incomparable.profile(incomparables.getLength() == 1 && incomparables instanceof RLogicalVector && ((RAbstractLogicalVector) incomparables).getDataAt(0) == RRuntime.LOGICAL_FALSE)) { + return false; + } else { + return true; + } } @SuppressWarnings("unused") - @Specialization(guards = {"!isIncomparable(incomparables)", "!empty(x)"}) + @Specialization(guards = {"!isIncomparable(incomparables)", "x.getLength() != 0"}) protected int anyDuplicatedFalseIncomparables(RAbstractVector x, RAbstractVector incomparables, byte fromLast) { return DuplicationHelper.analyze(x, null, true, RRuntime.fromLogical(fromLast)).getIndex(); } - @Specialization(guards = {"isIncomparable(incomparables)", "!empty(x)"}) - protected int anyDuplicatedTrueIncomparables(RAbstractVector x, RAbstractVector incomparables, byte fromLast) { - initChildren(); + protected static TypeofNode createTypeof() { + return TypeofNodeGen.create(); + } + + protected static CastTypeNode createCastType() { + return CastTypeNodeGen.create(); + } + + @Specialization(guards = {"isIncomparable(incomparables)", "x.getLength() != 0"}) + protected int anyDuplicatedTrueIncomparables(RAbstractVector x, RAbstractVector incomparables, byte fromLast, + @Cached("createTypeof()") TypeofNode typeof, + @Cached("createCastType()") CastTypeNode castTypeNode) { RType xType = typeof.execute(x); return DuplicationHelper.analyze(x, (RAbstractVector) (castTypeNode.execute(incomparables, xType)), true, RRuntime.fromLogical(fromLast)).getIndex(); } - @Specialization(guards = {"notAbstractVector(incomparables)", "!empty(x)"}) + @Specialization(guards = {"!isRAbstractVector(incomparables)", "x.getLength() != 0"}) + @TruffleBoundary protected int anyDuplicatedTrueIncomparables(RAbstractVector x, Object incomparables, @SuppressWarnings("unused") byte fromLast) { - initChildren(); - RType xType = typeof.execute(x); // TODO: this is not quite correct, as passing expression generated some obscure error // message, but is it worth fixing - throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_COERCE, ((RTypedValue) incomparables).getRType().getName(), xType.getName()); + throw error(RError.Message.CANNOT_COERCE, TypeofNode.getTypeof(incomparables).getName(), TypeofNode.getTypeof(x).getName()); } @SuppressWarnings("unused") - @Specialization(guards = "empty(x)") + @Specialization(guards = "x.getLength() == 0") protected int anyDuplicatedEmpty(RAbstractVector x, Object incomparables, byte fromLast) { return 0; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java index 688dd47a2c24c7b206eb193eb929fc91085cde1b..1156a95d30ae2872f2e2c89d9a130509b324f968 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java @@ -58,7 +58,7 @@ public class DynLoadFunctions { private static final String DLLINFOLIST_CLASS = "DLLInfoList"; @RBuiltin(name = "dyn.load", visibility = OFF, kind = INTERNAL, parameterNames = {"lib", "local", "now", "unused"}, behavior = COMPLEX) - public abstract static class DynLoad extends RBuiltinNode { + public abstract static class DynLoad extends RBuiltinNode.Arg4 { @Child private DLL.LoadPackageDLLNode loadPackageDLLNode = DLL.LoadPackageDLLNode.create(); static { @@ -76,13 +76,13 @@ public class DynLoadFunctions { DLLInfo dllInfo = loadPackageDLLNode.execute(lib, local, now); return dllInfo.toRList(); } catch (DLLException ex) { - throw RError.error(RError.SHOW_CALLER, ex); + throw error(ex); } } } @RBuiltin(name = "dyn.unload", visibility = OFF, kind = INTERNAL, parameterNames = {"lib"}, behavior = COMPLEX) - public abstract static class DynUnload extends RBuiltinNode { + public abstract static class DynUnload extends RBuiltinNode.Arg1 { @Child DLL.UnloadNode dllUnloadNode = DLL.UnloadNode.create(); static { @@ -96,14 +96,14 @@ public class DynLoadFunctions { try { dllUnloadNode.execute(lib.getDataAt(0)); } catch (DLLException ex) { - throw RError.error(this, ex); + throw error(ex); } return RNull.instance; } } @RBuiltin(name = "getLoadedDLLs", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) - public abstract static class GetLoadedDLLs extends RBuiltinNode { + public abstract static class GetLoadedDLLs extends RBuiltinNode.Arg0 { @Child private SetClassAttributeNode setClassAttrNode = SetClassAttributeNode.create(); @@ -126,7 +126,7 @@ public class DynLoadFunctions { } @RBuiltin(name = "is.loaded", kind = INTERNAL, parameterNames = {"symbol", "PACKAGE", "type"}, behavior = READS_STATE) - public abstract static class IsLoaded extends RBuiltinNode { + public abstract static class IsLoaded extends RBuiltinNode.Arg3 { @Child DLL.RFindSymbolNode findSymbolNode = DLL.RFindSymbolNode.create(); static { @@ -162,7 +162,7 @@ public class DynLoadFunctions { } @RBuiltin(name = "getSymbolInfo", kind = INTERNAL, parameterNames = {"symbol", "package", "withRegistrationInfo"}, behavior = READS_STATE) - public abstract static class GetSymbolInfo extends RBuiltinNode { + public abstract static class GetSymbolInfo extends RBuiltinNode.Arg3 { @Child DLL.RFindSymbolNode findSymbolNode = DLL.RFindSymbolNode.create(); static { @@ -189,7 +189,7 @@ public class DynLoadFunctions { @Cached("create()") DLL.RdlsymNode dlsymNode) { DLL.DLLInfo dllInfo = (DLLInfo) externalPtr.getExternalObject(); if (dllInfo == null) { - throw RError.error(this, RError.Message.REQUIRES_NAME_DLLINFO); + throw error(RError.Message.REQUIRES_NAME_DLLINFO); } DLL.RegisteredNativeSymbol rns = DLL.RegisteredNativeSymbol.any(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodeString.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodeString.java index 2cdec5a98cd8b5e42dffc9cff0b8dfe6c72a0ef1..edff830f7290665d07eb221b1e6d6af7d14e77b2 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodeString.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodeString.java @@ -36,7 +36,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "encodeString", kind = INTERNAL, parameterNames = {"x", "width", "quote", "justify", "na.encode"}, behavior = READS_STATE) -public abstract class EncodeString extends RBuiltinNode { +public abstract class EncodeString extends RBuiltinNode.Arg5 { private enum JUSTIFY { LEFT, diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodingFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodingFunctions.java index 9b05c97603454440b261b60deb0efcca08517372..e06312a5ede08cdc45e8732e122d35663ddd897d 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodingFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodingFunctions.java @@ -38,11 +38,11 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; public class EncodingFunctions { @RBuiltin(name = "Encoding", kind = INTERNAL, parameterNames = "x", behavior = PURE) - public abstract static class Encoding extends RBuiltinNode { + public abstract static class Encoding extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(Encoding.class); - casts.arg("x").mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.CHAR_VEC_ARGUMENT); + casts.arg("x").mustBe(stringValue(), RError.Message.CHAR_VEC_ARGUMENT); } @Specialization @@ -53,14 +53,14 @@ public class EncodingFunctions { } @RBuiltin(name = "setEncoding", kind = INTERNAL, parameterNames = {"x", "value"}, behavior = PURE) - public abstract static class SetEncoding extends RBuiltinNode { + public abstract static class SetEncoding extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(SetEncoding.class); - casts.arg("x").defaultError(RError.SHOW_CALLER, RError.Message.CHAR_VEC_ARGUMENT).mustBe(stringValue()); + casts.arg("x").defaultError(RError.Message.CHAR_VEC_ARGUMENT).mustBe(stringValue()); // asStringVector is required for notEmpty() to receive a proper type in case of scalars - casts.arg("value").defaultError(RError.SHOW_CALLER, RError.Message.GENERIC, "a character vector 'value' expected").mustBe(stringValue()).asStringVector().mustBe(notEmpty(), - RError.SHOW_CALLER, RError.Message.GENERIC, "'value' must be of positive length"); + casts.arg("value").defaultError(RError.Message.GENERIC, "a character vector 'value' expected").mustBe(stringValue()).asStringVector().mustBe(notEmpty(), + RError.Message.GENERIC, "'value' must be of positive length"); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java index f71df176ee575c5d9ef4763d9cfae8d4ff430b3b..1f9ed8bb2281941355312a476d4316dcd3249e62 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java @@ -42,17 +42,21 @@ import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.frame.FrameSlot; +import com.oracle.truffle.api.frame.FrameSlotKind; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.RRootNode; +import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode; import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.RList2EnvNode; import com.oracle.truffle.r.nodes.builtin.base.EnvFunctionsFactory.CopyNodeGen; +import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; import com.oracle.truffle.r.nodes.function.GetCallerFrameNode; import com.oracle.truffle.r.nodes.function.PromiseHelperNode; import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseDeoptimizeFrameNode; @@ -64,6 +68,7 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.VirtualEvalFrame; 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.RFunction; import com.oracle.truffle.r.runtime.data.RLanguage; @@ -80,6 +85,7 @@ 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; import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.env.frame.ActiveBinding; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; /** @@ -87,12 +93,8 @@ import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; */ public class EnvFunctions { - protected abstract static class Adapter extends RBuiltinNode { - protected final BranchProfile errorProfile = BranchProfile.create(); - } - @RBuiltin(name = "as.environment", kind = PRIMITIVE, parameterNames = {"fun"}, dispatch = INTERNAL_GENERIC, behavior = COMPLEX) - public abstract static class AsEnvironment extends Adapter { + public abstract static class AsEnvironment extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(AsEnvironment.class); @@ -101,7 +103,7 @@ public class EnvFunctions { @Specialization protected REnvironment asEnvironment(@SuppressWarnings("unused") RNull rnull) { - throw RError.error(this, RError.Message.AS_ENV_NULL_DEFUNCT); + throw error(RError.Message.AS_ENV_NULL_DEFUNCT); } @Specialization @@ -114,7 +116,7 @@ public class EnvFunctions { @Cached("new()") GetCallerFrameNode getCallerFrame) { if (pos.getLength() == 0) { CompilerDirectives.transferToInterpreter(); - throw RError.error(this, Message.INVALID_ARGUMENT, "pos"); + throw error(Message.INVALID_ARGUMENT, "pos"); } Object[] results = pos.getLength() == 1 ? null : new Object[pos.getLength()]; for (int i = 0; i < pos.getLength(); i++) { @@ -122,8 +124,7 @@ public class EnvFunctions { int p = pos.getDataAt(i); if (p == -1) { if (RArguments.getDepth(frame) == 0) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NO_ENCLOSING_ENVIRONMENT); + throw error(RError.Message.NO_ENCLOSING_ENVIRONMENT); } Frame callerFrame = getCallerFrame.execute(frame); env = REnvironment.frameToEnvironment(callerFrame.materialize()); @@ -146,8 +147,7 @@ public class EnvFunctions { // not accessible by name, GnuR allows it to be accessible by index return REnvironment.emptyEnv(); } else if ((p <= 0) || (p > searchPath.length + 1)) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "pos"); + throw error(RError.Message.INVALID_ARGUMENT, "pos"); } else { return REnvironment.lookupOnSearchPath(searchPath[p - 1]); } @@ -163,8 +163,7 @@ public class EnvFunctions { return REnvironment.lookupOnSearchPath(e); } } - errorProfile.enter(); - throw RError.error(this, RError.Message.NO_ITEM_NAMED, name); + throw error(RError.Message.NO_ITEM_NAMED, name); } @Specialization @@ -185,7 +184,7 @@ public class EnvFunctions { // generic dispatch tried already Object xData = getXDataAttrNode.execute(obj); if (xData == null || !(xData instanceof REnvironment)) { - throw RError.error(this, RError.Message.S4OBJECT_NX_ENVIRONMENT); + throw error(RError.Message.S4OBJECT_NX_ENVIRONMENT); } else { return xData; } @@ -193,12 +192,12 @@ public class EnvFunctions { @Fallback protected REnvironment asEnvironment(@SuppressWarnings("unused") Object object) { - throw RError.error(this, RError.Message.INVALID_OBJECT); + throw error(RError.Message.INVALID_OBJECT); } } @RBuiltin(name = "emptyenv", kind = PRIMITIVE, parameterNames = {}, behavior = PURE) - public abstract static class EmptyEnv extends RBuiltinNode { + public abstract static class EmptyEnv extends RBuiltinNode.Arg0 { @Specialization protected REnvironment emptyenv() { @@ -207,7 +206,7 @@ public class EnvFunctions { } @RBuiltin(name = "globalenv", kind = PRIMITIVE, parameterNames = {}, behavior = PURE) - public abstract static class GlobalEnv extends RBuiltinNode { + public abstract static class GlobalEnv extends RBuiltinNode.Arg0 { @Specialization protected Object globalenv() { @@ -219,7 +218,7 @@ public class EnvFunctions { * Returns the "package:base" environment. */ @RBuiltin(name = "baseenv", kind = PRIMITIVE, parameterNames = {}, behavior = PURE) - public abstract static class BaseEnv extends RBuiltinNode { + public abstract static class BaseEnv extends RBuiltinNode.Arg0 { @Specialization protected Object baseenv() { @@ -228,7 +227,7 @@ public class EnvFunctions { } @RBuiltin(name = "topenv", kind = INTERNAL, parameterNames = {"envir", "matchThisEnv"}, behavior = COMPLEX) - public abstract static class TopEnv extends Adapter { + public abstract static class TopEnv extends RBuiltinNode.Arg2 { static { Casts.noCasts(TopEnv.class); @@ -236,6 +235,9 @@ public class EnvFunctions { @Child private FrameFunctions.ParentFrame parentFrameNode; + @Override + public abstract Object execute(VirtualFrame frame, Object execute, Object instance); + @Specialization protected REnvironment topEnv(REnvironment env, REnvironment matchThisEnv) { return doTopEnv(matchThisEnv, env); @@ -268,7 +270,7 @@ public class EnvFunctions { } @TruffleBoundary - private static REnvironment doTopEnv(REnvironment target, final REnvironment envArg) { + private static REnvironment doTopEnv(REnvironment target, REnvironment envArg) { REnvironment env = envArg; while (env != REnvironment.emptyEnv()) { if (env == target || env == REnvironment.globalEnv() || env == REnvironment.baseEnv() || env == REnvironment.baseNamespaceEnv() || env.isPackageEnv() != null || env.isNamespaceEnv() || @@ -279,28 +281,28 @@ public class EnvFunctions { } return REnvironment.globalEnv(); } + } @RBuiltin(name = "parent.env", kind = INTERNAL, parameterNames = {"env"}, behavior = READS_FRAME) - public abstract static class ParentEnv extends Adapter { + public abstract static class ParentEnv extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(ParentEnv.class); - casts.arg("env").mustBe(instanceOf(REnvironment.class), RError.SHOW_CALLER, Message.ARGUMENT_NOT_ENVIRONMENT); + casts.arg("env").mustBe(instanceOf(REnvironment.class), Message.ARGUMENT_NOT_ENVIRONMENT); } @Specialization protected REnvironment parentenv(REnvironment env) { if (env == REnvironment.emptyEnv()) { - errorProfile.enter(); - throw RError.error(RError.SHOW_CALLER, RError.Message.EMPTY_NO_PARENT); + throw error(RError.Message.EMPTY_NO_PARENT); } return env.getParent(); } } @RBuiltin(name = "parent.env<-", kind = INTERNAL, parameterNames = {"env", "value"}, behavior = COMPLEX) - public abstract static class SetParentEnv extends Adapter { + public abstract static class SetParentEnv extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(SetParentEnv.class); @@ -312,7 +314,7 @@ public class EnvFunctions { @TruffleBoundary protected REnvironment setParentenv(REnvironment env, REnvironment parent) { if (env == REnvironment.emptyEnv()) { - throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_SET_PARENT); + throw error(RError.Message.CANNOT_SET_PARENT); } env.setParent(parent); return env; @@ -320,7 +322,7 @@ public class EnvFunctions { } @RBuiltin(name = "is.environment", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) - public abstract static class IsEnvironment extends RBuiltinNode { + public abstract static class IsEnvironment extends RBuiltinNode.Arg1 { static { Casts.noCasts(IsEnvironment.class); @@ -333,7 +335,7 @@ public class EnvFunctions { } @RBuiltin(name = "environment", kind = INTERNAL, parameterNames = {"fun"}, behavior = COMPLEX) - public abstract static class Environment extends RBuiltinNode { + public abstract static class Environment extends RBuiltinNode.Arg1 { private final ConditionProfile attributable = ConditionProfile.createBinaryProfile(); @Child private GetFixedAttributeNode getEnvAttrNode; @@ -371,25 +373,29 @@ public class EnvFunctions { return env; } - @Specialization(guards = "isRFormula(formula)") - protected Object environment(RLanguage formula) { - if (getEnvAttrNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - getEnvAttrNode = insert(GetFixedAttributeNode.create(RRuntime.DOT_ENVIRONMENT)); + @Specialization + @TruffleBoundary + protected Object environmentLanguage(RLanguage value) { + if (ClassHierarchyNode.hasClass(value, RRuntime.FORMULA_CLASS)) { + if (getEnvAttrNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + getEnvAttrNode = insert(GetFixedAttributeNode.create(RRuntime.DOT_ENVIRONMENT)); + } + Object result = getEnvAttrNode.execute(value); + return result == null ? RNull.instance : result; + } else { + return environment(value); } - - Object result = getEnvAttrNode.execute(formula); - return result == null ? RNull.instance : result; } - @Specialization(guards = {"!isRNull(fun)", "!isRFunction(fun)", "!isRFormula(fun)"}) - protected Object environment(Object fun) { - if (attributable.profile(fun instanceof RAttributable)) { + @Specialization(guards = {"!isRNull(value)", "!isRFunction(value)", "!isRLanguage(value)"}) + protected Object environment(Object value) { + if (attributable.profile(value instanceof RAttributable)) { if (getEnvAttrNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); getEnvAttrNode = insert(GetFixedAttributeNode.create(RRuntime.DOT_ENVIRONMENT)); } - Object attr = getEnvAttrNode.execute(fun); + Object attr = getEnvAttrNode.execute(value); return attr == null ? RNull.instance : attr; } else { // Not an error according to GnuR @@ -399,7 +405,7 @@ public class EnvFunctions { } @RBuiltin(name = "environment<-", kind = PRIMITIVE, parameterNames = {"env", "value"}, behavior = COMPLEX) - public abstract static class UpdateEnvironment extends RBuiltinNode { + public abstract static class UpdateEnvironment extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(UpdateEnvironment.class); @@ -418,13 +424,19 @@ public class EnvFunctions { RRootNode root = (RRootNode) fun.getTarget().getRootNode(); RootCallTarget target = root.duplicateWithNewFrameDescriptor(); FrameSlotChangeMonitor.initializeEnclosingFrame(target.getRootNode().getFrameDescriptor(), enclosingFrame); - return RDataFactory.createFunction(fun.getName(), fun.getPackageName(), target, null, enclosingFrame); + + RFunction newFunction = RDataFactory.createFunction(fun.getName(), fun.getPackageName(), target, null, enclosingFrame); + if (fun.getAttributes() != null) { + newFunction.initAttributes(RAttributesLayout.copy(fun.getAttributes())); + } + newFunction.setTypedValueInfo(fun.getTypedValueInfo()); + return newFunction; } @Specialization @TruffleBoundary protected Object updateEnvironment(@SuppressWarnings("unused") RFunction fun, @SuppressWarnings("unused") RNull env) { - throw RError.error(this, RError.Message.USE_NULL_ENV_DEFUNCT); + throw error(RError.Message.USE_NULL_ENV_DEFUNCT); } protected SetFixedAttributeNode createSetEnvAttrNode() { @@ -468,12 +480,12 @@ public class EnvFunctions { @Specialization @TruffleBoundary protected Object updateEnvironment(@SuppressWarnings("unused") RNull obj, @SuppressWarnings("unused") REnvironment env) { - throw RError.error(this, Message.SET_ATTRIBUTES_ON_NULL); + throw error(Message.SET_ATTRIBUTES_ON_NULL); } } @RBuiltin(name = "environmentName", kind = INTERNAL, parameterNames = {"fun"}, behavior = PURE) - public abstract static class EnvironmentName extends RBuiltinNode { + public abstract static class EnvironmentName extends RBuiltinNode.Arg1 { static { Casts.noCasts(EnvironmentName.class); @@ -492,7 +504,7 @@ public class EnvFunctions { } @RBuiltin(name = "new.env", kind = INTERNAL, parameterNames = {"hash", "parent", "size"}, behavior = COMPLEX) - public abstract static class NewEnv extends RBuiltinNode { + public abstract static class NewEnv extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(NewEnv.class); @@ -511,7 +523,7 @@ public class EnvFunctions { } @RBuiltin(name = "search", kind = INTERNAL, parameterNames = {}, behavior = COMPLEX) - public abstract static class Search extends RBuiltinNode { + public abstract static class Search extends RBuiltinNode.Arg0 { @Specialization protected RStringVector search() { return RDataFactory.createStringVector(REnvironment.searchPath(), RDataFactory.COMPLETE_VECTOR); @@ -519,11 +531,11 @@ public class EnvFunctions { } @RBuiltin(name = "lockEnvironment", visibility = OFF, kind = INTERNAL, parameterNames = {"env", "bindings"}, behavior = COMPLEX) - public abstract static class LockEnvironment extends RBuiltinNode { + public abstract static class LockEnvironment extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(LockEnvironment.class); - casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT); + casts.arg("env").mustBe(REnvironment.class, Message.NOT_AN_ENVIRONMENT); // TODO: the actual interpretation of this parameter remains dubious casts.arg("bindings").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); } @@ -536,11 +548,11 @@ public class EnvFunctions { } @RBuiltin(name = "environmentIsLocked", kind = INTERNAL, parameterNames = {"env"}, behavior = PURE) - public abstract static class EnvironmentIsLocked extends RBuiltinNode { + public abstract static class EnvironmentIsLocked extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(EnvironmentIsLocked.class); - casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT); + casts.arg("env").mustBe(REnvironment.class, Message.NOT_AN_ENVIRONMENT); } @Specialization @@ -550,12 +562,12 @@ public class EnvFunctions { } @RBuiltin(name = "lockBinding", visibility = OFF, kind = INTERNAL, parameterNames = {"sym", "env"}, behavior = COMPLEX) - public abstract static class LockBinding extends RBuiltinNode { + public abstract static class LockBinding extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(LockBinding.class); - casts.arg("sym").mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL); - casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT); + casts.arg("sym").mustBe(RSymbol.class, Message.NOT_A_SYMBOL); + casts.arg("env").mustBe(REnvironment.class, Message.NOT_AN_ENVIRONMENT); } @Specialization @@ -566,12 +578,12 @@ public class EnvFunctions { } @RBuiltin(name = "unlockBinding", visibility = OFF, kind = INTERNAL, parameterNames = {"sym", "env"}, behavior = COMPLEX) - public abstract static class UnlockBinding extends RBuiltinNode { + public abstract static class UnlockBinding extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(UnlockBinding.class); - casts.arg("sym").mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL); - casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT); + casts.arg("sym").mustBe(RSymbol.class, Message.NOT_A_SYMBOL); + casts.arg("env").mustBe(REnvironment.class, Message.NOT_AN_ENVIRONMENT); } @Specialization @@ -582,12 +594,12 @@ public class EnvFunctions { } @RBuiltin(name = "bindingIsLocked", kind = INTERNAL, parameterNames = {"sym", "env"}, behavior = PURE) - public abstract static class BindingIsLocked extends RBuiltinNode { + public abstract static class BindingIsLocked extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(BindingIsLocked.class); - casts.arg("sym").mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL); - casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT); + casts.arg("sym").mustBe(RSymbol.class, Message.NOT_A_SYMBOL); + casts.arg("env").mustBe(REnvironment.class, Message.NOT_AN_ENVIRONMENT); } @Specialization @@ -597,48 +609,77 @@ public class EnvFunctions { } @RBuiltin(name = "makeActiveBinding", visibility = OFF, kind = INTERNAL, parameterNames = {"sym", "fun", "env"}, behavior = COMPLEX) - public abstract static class MakeActiveBinding extends RBuiltinNode { + public abstract static class MakeActiveBinding extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(MakeActiveBinding.class); - casts.arg("sym").mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL); - casts.arg("fun").mustBe(RFunction.class, RError.SHOW_CALLER, Message.NOT_A_FUNCTION); - casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT); + casts.arg("sym").mustBe(RSymbol.class, Message.NOT_A_SYMBOL); + casts.arg("fun").mustBe(RFunction.class, Message.NOT_A_FUNCTION); + casts.arg("env").mustBe(REnvironment.class, Message.NOT_AN_ENVIRONMENT); } - @SuppressWarnings("unused") + private BranchProfile frameSlotBranchProfile; + + @TruffleBoundary @Specialization - protected Object makeActiveBinding(Object sym, Object fun, Object env) { - // TODO implement - throw RError.nyi(this, "makeActiveBinding"); + protected Object makeActiveBinding(RSymbol sym, RFunction fun, REnvironment env) { + if (frameSlotBranchProfile == null) { + frameSlotBranchProfile = BranchProfile.create(); + } + + String name = sym.getName(); + MaterializedFrame frame = env.getFrame(); + Object binding = ReadVariableNode.lookupAny(name, frame, true); + if (binding == null) { + if (!env.isLocked()) { + FrameSlot slot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), name, FrameSlotKind.Object); + FrameSlotChangeMonitor.setActiveBinding(frame, slot, new ActiveBinding(sym.getRType(), fun), false, frameSlotBranchProfile); + binding = ReadVariableNode.lookupAny(name, frame, true); + assert binding != null; + assert binding instanceof ActiveBinding; + } else { + throw error(RError.Message.CANNOT_ADD_BINDINGS); + } + } else if (!ActiveBinding.isActiveBinding(binding)) { + throw error(RError.Message.SYMBOL_HAS_REGULAR_BINDING); + } else if (env.bindingIsLocked(name)) { + throw error(RError.Message.CANNOT_CHANGE_LOCKED_ACTIVE_BINDING); + } else { + // update active binding + FrameSlot slot = frame.getFrameDescriptor().findFrameSlot(name); + FrameSlotChangeMonitor.setActiveBinding(frame, slot, new ActiveBinding(sym.getRType(), fun), false, frameSlotBranchProfile); + } + return RNull.instance; } } @RBuiltin(name = "bindingIsActive", kind = INTERNAL, parameterNames = {"sym", "env"}, behavior = PURE) - public abstract static class BindingIsActive extends RBuiltinNode { + public abstract static class BindingIsActive extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(BindingIsActive.class); - casts.arg("sym").mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL); - casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT); + casts.arg("sym").mustBe(RSymbol.class, Message.NOT_A_SYMBOL); + casts.arg("env").mustBe(REnvironment.class, Message.NOT_AN_ENVIRONMENT); } - @SuppressWarnings("unused") @Specialization - protected Object bindingIsActive(Object sym, Object env) { - // TODO implement - throw RError.nyi(this, "bindingIsActive"); + protected Object bindingIsActive(RSymbol sym, REnvironment env) { + Object binding = ReadVariableNode.lookupAny(sym.getName(), env.getFrame(), true); + if (binding == null) { + throw error(RError.Message.NO_BINDING_FOR, sym.getName()); + } + return RDataFactory.createLogicalVectorFromScalar(ActiveBinding.isActiveBinding(binding)); } } @RBuiltin(name = "env2list", kind = INTERNAL, parameterNames = {"x", "all.names", "sorted"}, behavior = PURE) - public abstract static class EnvToList extends RBuiltinNode { + public abstract static class EnvToList extends RBuiltinNode.Arg3 { @Child private CopyNode copy; static { Casts casts = new Casts(EnvToList.class); - casts.arg("x").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT); + casts.arg("x").mustBe(REnvironment.class, Message.NOT_AN_ENVIRONMENT); casts.arg("all.names").mustNotBeNull().asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); casts.arg("sorted").mustNotBeNull().asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); } @@ -732,6 +773,11 @@ public class EnvFunctions { return env; } + @Specialization + Object copy(RS4Object o) { + return o.copy(); + } + @Fallback Object copy(@SuppressWarnings("unused") Object o) { throw RInternalError.unimplemented("copying of object in the environment not supported"); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java index 3367d84ad0838348813259ff5493955ce0d695d6..1a2c94f5c7672ef8d4a1b803f0c92c4b65b3e287 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java @@ -37,6 +37,7 @@ 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.frame.VirtualFrame; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.EvalNodeGen.EvalEnvCastNodeGen; import com.oracle.truffle.r.nodes.builtin.base.FrameFunctions.SysFrame; @@ -45,6 +46,7 @@ import com.oracle.truffle.r.nodes.builtin.base.GetFunctionsFactory.GetNodeGen; import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.ReturnException; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RExpression; @@ -60,7 +62,12 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; * Contains the {@code eval} {@code .Internal} implementation. */ @RBuiltin(name = "eval", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"expr", "envir", "enclos"}, behavior = COMPLEX) -public abstract class Eval extends RBuiltinNode { +public abstract class Eval extends RBuiltinNode.Arg3 { + + /** + * Profiling for catching {@link ReturnException}s. + */ + private final ConditionProfile returnTopLevelProfile = ConditionProfile.createBinaryProfile(); /** * Eval takes two arguments that specify the environment where the expression should be @@ -146,6 +153,12 @@ public abstract class Eval extends RBuiltinNode { REnvironment environment = envCast.execute(frame, envir, enclos); try { return RContext.getEngine().eval(expr, environment, rCaller); + } catch (ReturnException ret) { + if (returnTopLevelProfile.profile(ret.getTarget() == rCaller)) { + return ret.getResult(); + } else { + throw ret; + } } finally { visibility.executeAfterCall(frame, rCaller); } @@ -157,6 +170,12 @@ public abstract class Eval extends RBuiltinNode { REnvironment environment = envCast.execute(frame, envir, enclos); try { return RContext.getEngine().eval(expr, environment, rCaller); + } catch (ReturnException ret) { + if (returnTopLevelProfile.profile(ret.getTarget() == rCaller)) { + return ret.getResult(); + } else { + throw ret; + } } finally { visibility.executeAfterCall(frame, rCaller); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Exists.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Exists.java index f08f18daa3dc3478474890ca9636265be26f71f3..2e8a04837d0705b28bb39734801bcd3b40776db6 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Exists.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Exists.java @@ -42,7 +42,7 @@ import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.env.REnvironment; @RBuiltin(name = "exists", kind = INTERNAL, parameterNames = {"x", "envir", "mode", "inherits"}, behavior = PURE) -public abstract class Exists extends RBuiltinNode { +public abstract class Exists extends RBuiltinNode.Arg4 { @Child private TypeFromModeNode typeFromMode = TypeFromModeNodeGen.create(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java index f4b9d0c8e54fa4bd3fc9f9798019d4f8278b0496..6e245e1ed74d87338ed744ce95b59203b8df644d 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java @@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RPromise; @RBuiltin(name = "expression", kind = PRIMITIVE, parameterNames = {"..."}, nonEvalArgs = 0, behavior = PURE) -public abstract class Expression extends RBuiltinNode { +public abstract class Expression extends RBuiltinNode.Arg1 { /* * Owing to the nonEvalArgs, all arguments are RPromise, but an expression may contain * non-RLanguage elements. diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java index 5534dd45050b4bc9447f05bdc8bc2ab287a97d30..2b33757ec46aa25f0170a3c31f779b4e120d4707 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java @@ -20,6 +20,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lte; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.runtime.RVisibility.OFF; import static com.oracle.truffle.r.runtime.builtins.RBehavior.IO; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -87,7 +88,7 @@ import com.oracle.truffle.r.runtime.ffi.BaseRFFI; public class FileFunctions { @RBuiltin(name = "file.access", kind = INTERNAL, parameterNames = {"names", "mode"}, behavior = IO) - public abstract static class FileAccess extends RBuiltinNode { + public abstract static class FileAccess extends RBuiltinNode.Arg2 { private static final int EXECUTE = 1; private static final int WRITE = 2; private static final int READ = 4; @@ -123,7 +124,7 @@ public class FileFunctions { } @RBuiltin(name = "file.append", kind = INTERNAL, parameterNames = {"file1", "file2"}, behavior = IO) - public abstract static class FileAppend extends RBuiltinNode { + public abstract static class FileAppend extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(FileAppend.class); @@ -146,7 +147,7 @@ public class FileFunctions { int len1 = file1Vec.getLength(); int len2 = file2Vec.getLength(); if (len1 < 1) { - throw RError.error(this, RError.Message.FILE_APPEND_TO); + throw error(RError.Message.FILE_APPEND_TO); } if (len2 < 1) { return RDataFactory.createEmptyLogicalVector(); @@ -211,7 +212,7 @@ public class FileFunctions { out.write(buf); return true; } catch (IOException ex) { - RError.warning(this, RError.Message.FILE_APPEND_WRITE); + warning(RError.Message.FILE_APPEND_WRITE); return false; } } @@ -219,7 +220,7 @@ public class FileFunctions { } @RBuiltin(name = "file.create", kind = INTERNAL, parameterNames = {"vec", "showWarnings"}, behavior = IO) - public abstract static class FileCreate extends RBuiltinNode { + public abstract static class FileCreate extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(FileCreate.class); @@ -242,7 +243,7 @@ public class FileFunctions { } catch (IOException ex) { ok = false; if (showWarnings == RRuntime.LOGICAL_TRUE) { - RError.warning(this, RError.Message.FILE_CANNOT_CREATE, path); + warning(RError.Message.FILE_CANNOT_CREATE, path); } } status[i] = RRuntime.asLogical(ok); @@ -253,7 +254,7 @@ public class FileFunctions { } @RBuiltin(name = "file.info", kind = INTERNAL, parameterNames = {"fn", "extra_cols"}, behavior = IO) - public abstract static class FileInfo extends RBuiltinNode { + public abstract static class FileInfo extends RBuiltinNode.Arg2 { // @formatter:off private enum Column { size, isdir, mode, mtime, ctime, atime, uid, gid, uname, grname; @@ -423,10 +424,10 @@ public class FileFunctions { } } - private abstract static class FileLinkAdaptor extends RBuiltinNode { + private abstract static class FileLinkAdaptor extends RBuiltinNode.Arg2 { - static { - Casts casts = new Casts(FileLinkAdaptor.class); + protected static void casts(Class<? extends FileLinkAdaptor> builtinClass) { + Casts casts = new Casts(builtinClass); casts.arg("from").mustBe(stringValue(), RError.Message.INVALID_FIRST_FILENAME).asStringVector(); casts.arg("to").mustBe(stringValue(), RError.Message.INVALID_SECOND_FILENAME).asStringVector(); } @@ -435,7 +436,7 @@ public class FileFunctions { int lenFrom = vecFrom.getLength(); int lenTo = vecTo.getLength(); if (lenFrom < 1) { - throw RError.error(this, RError.Message.NOTHING_TO_LINK); + throw error(RError.Message.NOTHING_TO_LINK); } if (lenTo < 1) { return RDataFactory.createLogicalVector(0); @@ -460,7 +461,7 @@ public class FileFunctions { } } catch (UnsupportedOperationException | IOException ex) { status[i] = RRuntime.LOGICAL_FALSE; - RError.warning(this, RError.Message.FILE_CANNOT_LINK, from, to, ex.getMessage()); + warning(RError.Message.FILE_CANNOT_LINK, from, to, ex.getMessage()); } } } @@ -470,6 +471,13 @@ public class FileFunctions { @RBuiltin(name = "file.link", kind = INTERNAL, parameterNames = {"from", "to"}, behavior = IO) public abstract static class FileLink extends FileLinkAdaptor { + + static { + Casts casts = new Casts(FileLink.class); + casts.arg("from").mustBe(stringValue(), RError.Message.INVALID_FIRST_FILENAME).asStringVector(); + casts.arg("to").mustBe(stringValue(), RError.Message.INVALID_SECOND_FILENAME).asStringVector(); + } + @Specialization @TruffleBoundary protected Object doFileLink(RAbstractStringVector vecFrom, RAbstractStringVector vecTo) { @@ -479,6 +487,13 @@ public class FileFunctions { @RBuiltin(name = "file.symlink", kind = INTERNAL, parameterNames = {"from", "to"}, behavior = IO) public abstract static class FileSymLink extends FileLinkAdaptor { + + static { + Casts casts = new Casts(FileSymLink.class); + casts.arg("from").mustBe(stringValue(), RError.Message.INVALID_FIRST_FILENAME).asStringVector(); + casts.arg("to").mustBe(stringValue(), RError.Message.INVALID_SECOND_FILENAME).asStringVector(); + } + @Specialization @TruffleBoundary protected Object doFileSymLink(RAbstractStringVector vecFrom, RAbstractStringVector vecTo) { @@ -487,7 +502,7 @@ public class FileFunctions { } @RBuiltin(name = "file.remove", kind = INTERNAL, parameterNames = {"file"}, behavior = IO) - public abstract static class FileRemove extends RBuiltinNode { + public abstract static class FileRemove extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(FileRemove.class); @@ -507,7 +522,7 @@ public class FileFunctions { boolean ok = f.delete(); status[i] = RRuntime.asLogical(ok); if (!ok) { - RError.warning(this, RError.Message.FILE_CANNOT_REMOVE, path); + warning(RError.Message.FILE_CANNOT_REMOVE, path); } } } @@ -516,7 +531,7 @@ public class FileFunctions { } @RBuiltin(name = "file.rename", kind = INTERNAL, parameterNames = {"from", "to"}, behavior = IO) - public abstract static class FileRename extends RBuiltinNode { + public abstract static class FileRename extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(FileRename.class); @@ -529,7 +544,7 @@ public class FileFunctions { protected Object doFileRename(RAbstractStringVector vecFrom, RAbstractStringVector vecTo) { int len = vecFrom.getLength(); if (len != vecTo.getLength()) { - throw RError.error(this, RError.Message.FROM_TO_DIFFERENT); + throw error(RError.Message.FROM_TO_DIFFERENT); } byte[] status = new byte[len]; for (int i = 0; i < len; i++) { @@ -543,7 +558,7 @@ public class FileFunctions { boolean ok = new File(Utils.tildeExpand(from)).renameTo(new File(Utils.tildeExpand(to))); status[i] = RRuntime.asLogical(ok); if (!ok) { - RError.warning(this, RError.Message.FILE_CANNOT_RENAME, from, to); + warning(RError.Message.FILE_CANNOT_RENAME, from, to); } } } @@ -552,7 +567,7 @@ public class FileFunctions { } @RBuiltin(name = "file.exists", kind = INTERNAL, parameterNames = {"file"}, behavior = IO) - public abstract static class FileExists extends RBuiltinNode { + public abstract static class FileExists extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(FileExists.class); @@ -565,7 +580,7 @@ public class FileFunctions { byte[] status = new byte[vec.getLength()]; for (int i = 0; i < status.length; i++) { String path = vec.getDataAt(i); - if (RRuntime.isNA(path)) { + if (RRuntime.isNA(path) || path.isEmpty()) { status[i] = RRuntime.LOGICAL_FALSE; } else { File f = new File(Utils.tildeExpand(path)); @@ -579,7 +594,7 @@ public class FileFunctions { // TODO Implement all the options @RBuiltin(name = "list.files", kind = INTERNAL, parameterNames = {"path", "pattern", "all.files", "full.names", "recursive", "ignore.case", "include.dirs", "no.."}, behavior = IO) - public abstract static class ListFiles extends RBuiltinNode { + public abstract static class ListFiles extends RBuiltinNode.Arg8 { private static final String DOT = "."; private static final String DOTDOT = ".."; @@ -587,12 +602,12 @@ public class FileFunctions { Casts casts = new Casts(ListFiles.class); casts.arg("path").mustBe(stringValue()).asStringVector(); casts.arg("pattern").allowNull().mustBe(stringValue()); - casts.arg("all.files").asLogicalVector().findFirst().notNA().map(toBoolean()); - casts.arg("full.names").asLogicalVector().findFirst().notNA().map(toBoolean()); - casts.arg("recursive").asLogicalVector().findFirst().notNA().map(toBoolean()); - casts.arg("ignore.case").asLogicalVector().findFirst().notNA().map(toBoolean()); - casts.arg("include.dirs").asLogicalVector().findFirst().notNA().map(toBoolean()); - casts.arg("no..").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("all.files").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); + casts.arg("full.names").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); + casts.arg("recursive").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); + casts.arg("ignore.case").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); + casts.arg("include.dirs").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); + casts.arg("no..").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } @SuppressWarnings("unused") @@ -617,7 +632,7 @@ public class FileFunctions { String pattern = null; if (patternVec.getLength() > 0) { if (RRuntime.isNA(patternVec.getDataAt(0))) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "pattern"); + throw error(RError.Message.INVALID_ARGUMENT, "pattern"); } else { pattern = patternVec.getDataAt(0); } @@ -688,7 +703,7 @@ public class FileFunctions { private boolean check(boolean value, String argName) { if (value) { - RError.warning(this, RError.Message.GENERIC, "'" + argName + "'" + " is not implemented"); + warning(RError.Message.GENERIC, "'" + argName + "'" + " is not implemented"); } return value; } @@ -723,13 +738,13 @@ public class FileFunctions { } @RBuiltin(name = "list.dirs", kind = INTERNAL, parameterNames = {"directory", "full.names", "recursive"}, behavior = IO) - public abstract static class ListDirs extends RBuiltinNode { + public abstract static class ListDirs extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(ListDirs.class); casts.arg("directory").mustBe(stringValue()).asStringVector(); - casts.arg("full.names").asLogicalVector().findFirst().notNA().map(toBoolean()); - casts.arg("recursive").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("full.names").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); + casts.arg("recursive").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } @Specialization @@ -779,12 +794,12 @@ public class FileFunctions { // TODO handle the general case, which is similar to paste @RBuiltin(name = "file.path", kind = INTERNAL, parameterNames = {"paths", "fsep"}, behavior = IO) - public abstract static class FilePath extends RBuiltinNode { + public abstract static class FilePath extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(FilePath.class); casts.arg("paths").mustBe(instanceOf(RList.class), RError.Message.INVALID_FIRST_ARGUMENT); - casts.arg("fsep").mustBe(stringValue()).asStringVector().findFirst().notNA(); + casts.arg("fsep").mustBe(stringValue()).asStringVector().findFirst().mustNotBeNA(); } @Child private CastStringNode castStringNode; @@ -842,7 +857,7 @@ public class FileFunctions { } else if (elem instanceof RStringVector) { inputs[i] = ((RStringVector) elem).getDataWithoutCopying(); } else { - throw RError.error(this, RError.Message.NON_STRING_ARG_TO_INTERNAL_PASTE); + throw error(RError.Message.NON_STRING_ARG_TO_INTERNAL_PASTE); } } for (int i = 0; i < resultLength; i++) { @@ -878,16 +893,16 @@ public class FileFunctions { * {@code file.copy} builtin. This is only called when the target is a directory. */ @RBuiltin(name = "file.copy", kind = INTERNAL, parameterNames = {"from", "to", "overwrite", "recursive", "copy.mode", "copy.date"}, behavior = IO) - public abstract static class FileCopy extends RBuiltinNode { + public abstract static class FileCopy extends RBuiltinNode.Arg6 { static { Casts casts = new Casts(FileCopy.class); casts.arg("from").mustBe(stringValue()).asStringVector(); casts.arg("to").mustBe(stringValue()).asStringVector(); - casts.arg("overwrite").asLogicalVector().findFirst().notNA().map(toBoolean()); - casts.arg("recursive").asLogicalVector().findFirst().notNA().map(toBoolean()); - casts.arg("copy.mode").asLogicalVector().findFirst().notNA().map(toBoolean()); - casts.arg("copy.date").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("overwrite").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); + casts.arg("recursive").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); + casts.arg("copy.mode").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); + casts.arg("copy.date").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } @Specialization @@ -899,7 +914,7 @@ public class FileFunctions { if (lenFrom > 0) { int lenTo = vecTo.getLength(); if (lenTo != 1) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "to"); + throw error(RError.Message.INVALID_ARGUMENT, "to"); } // Java cannot distinguish copy.mode and copy.dates @@ -925,7 +940,7 @@ public class FileFunctions { } if (recursive) { if (toDir == null) { - RError.warning(this, RError.Message.FILE_COPY_RECURSIVE_IGNORED); + warning(RError.Message.FILE_COPY_RECURSIVE_IGNORED); recursive = false; } } @@ -963,7 +978,7 @@ public class FileFunctions { } } catch (UnsupportedOperationException | IOException ex) { status[i] = RRuntime.LOGICAL_FALSE; - RError.warning(this, RError.Message.FILE_CANNOT_COPY, from, to, ex.getMessage()); + warning(RError.Message.FILE_CANNOT_COPY, from, to, ex.getMessage()); } } } @@ -1013,20 +1028,20 @@ public class FileFunctions { } @RBuiltin(name = "file.show", kind = INTERNAL, parameterNames = {"files", "header", "title", "delete.file", "pager"}, visibility = OFF, behavior = IO) - public abstract static class FileShow extends RBuiltinNode { + public abstract static class FileShow extends RBuiltinNode.Arg5 { static { Casts casts = new Casts(FileShow.class); - casts.arg("files").asStringVector(); - casts.arg("header").asStringVector(); - casts.arg("title").asStringVector(); + casts.arg("files").mustNotBeMissing().mustBe(nullValue().not(), Message.INVALID_FILENAME_SPECIFICATION).asStringVector(); + casts.arg("header").mustNotBeMissing().mustBe(nullValue().not(), Message.INVALID_ARG, "'headers'").asStringVector(); + casts.arg("title").mustNotBeMissing().mustBe(nullValue().not(), Message.INVALID_ARG, "'title'").asStringVector(); casts.arg("delete.file").asLogicalVector().findFirst().map(toBoolean()); casts.arg("pager").asStringVector().findFirst(); } @Specialization @TruffleBoundary - protected static RNull show(RAbstractStringVector files, RAbstractStringVector header, RAbstractStringVector title, boolean deleteFile, @SuppressWarnings("unused") String pager) { + protected RNull show(RAbstractStringVector files, RAbstractStringVector header, RAbstractStringVector title, boolean deleteFile, @SuppressWarnings("unused") String pager) { ConsoleHandler console = RContext.getInstance().getConsoleHandler(); for (int i = 0; i < title.getLength(); i++) { console.println("==== " + title.getDataAt(i) + " ===="); @@ -1045,7 +1060,7 @@ public class FileFunctions { path.toFile().delete(); } } catch (IOException e) { - throw RError.error(RError.SHOW_CALLER, Message.GENERIC, e.getMessage()); + throw error(Message.GENERIC, e.getMessage()); } } return RNull.instance; @@ -1071,7 +1086,7 @@ public class FileFunctions { } @RBuiltin(name = "dirname", kind = INTERNAL, parameterNames = {"path"}, behavior = IO) - public abstract static class DirName extends RBuiltinNode { + public abstract static class DirName extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(DirName.class); @@ -1090,7 +1105,7 @@ public class FileFunctions { } @RBuiltin(name = "basename", kind = INTERNAL, parameterNames = {"path"}, behavior = IO) - public abstract static class BaseName extends RBuiltinNode { + public abstract static class BaseName extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(BaseName.class); @@ -1109,13 +1124,13 @@ public class FileFunctions { } @RBuiltin(name = "unlink", visibility = OFF, kind = INTERNAL, parameterNames = {"x", "recursive", "force"}, behavior = IO) - public abstract static class Unlink extends RBuiltinNode { + public abstract static class Unlink extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(Unlink.class); casts.arg("x").mustBe(stringValue(), RError.Message.CHAR_VEC_ARGUMENT); - casts.arg("recursive").asLogicalVector().findFirst().notNA().map(toBoolean()); - casts.arg("force").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("recursive").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); + casts.arg("force").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } @Specialization @@ -1178,7 +1193,7 @@ public class FileFunctions { } @RBuiltin(name = "dir.create", visibility = OFF, kind = INTERNAL, parameterNames = {"path", "showWarnings", "recursive", "mode"}, behavior = IO) - public abstract static class DirCreate extends RBuiltinNode { + public abstract static class DirCreate extends RBuiltinNode.Arg4 { static { Casts casts = new Casts(DirCreate.class); @@ -1228,7 +1243,7 @@ public class FileFunctions { return true; } catch (IOException ex) { if (showWarnings) { - RError.warning(this, RError.Message.DIR_CANNOT_CREATE, path); + warning(RError.Message.DIR_CANNOT_CREATE, path); } return false; } @@ -1236,7 +1251,7 @@ public class FileFunctions { } @RBuiltin(name = "dir.exists", kind = INTERNAL, parameterNames = "paths", behavior = IO) - public abstract static class DirExists extends RBuiltinNode { + public abstract static class DirExists extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(DirExists.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForceAndCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForceAndCall.java index 3368086a659ce6075b865ceb209bfabdbddb19b2..3cef036d53cbbb707ffd9819a0bcb2f02abd496c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForceAndCall.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForceAndCall.java @@ -41,7 +41,7 @@ import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RPromise; @RBuiltin(name = "forceAndCall", kind = PRIMITIVE, parameterNames = {"n", "FUN", "..."}, nonEvalArgs = 2, behavior = COMPLEX) -public abstract class ForceAndCall extends RBuiltinNode { +public abstract class ForceAndCall extends RBuiltinNode.Arg3 { @Child private RExplicitCallNode call = RExplicitCallNode.create(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Formals.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Formals.java index ce083781b25870a75ff9adef33030549d86bac59..91e682f99967cba54c235fa4dc0aa4990d4befac 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Formals.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Formals.java @@ -41,7 +41,7 @@ import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.nodes.RNode; @RBuiltin(name = "formals", kind = INTERNAL, parameterNames = {"fun"}, behavior = PURE) -public abstract class Formals extends RBuiltinNode { +public abstract class Formals extends RBuiltinNode.Arg1 { static { Casts.noCasts(Formals.class); @@ -72,9 +72,6 @@ public abstract class Formals extends RBuiltinNode { return RNull.instance; } FunctionDefinitionNode fdNode = (FunctionDefinitionNode) fun.getTarget().getRootNode(); - if (fdNode.getParameterCount() == 0) { - return RNull.instance; - } FormalArguments formalArgs = fdNode.getFormalArguments(); Object succ = RNull.instance; for (int i = formalArgs.getSignature().getLength() - 1; i >= 0; i--) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java index ad0e3d20d3e60291bb8f9203c6e36f8d414f8a3a..6075cc51c5493d49521c59a05d26eba0b06d02c8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java @@ -19,19 +19,20 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.profiles.BranchProfile; -import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.builtin.base.printer.AnyVectorToStringVectorWriter; +import com.oracle.truffle.r.nodes.builtin.base.printer.ComplexVectorPrinter; +import com.oracle.truffle.r.nodes.builtin.base.printer.DoubleVectorPrinter; +import com.oracle.truffle.r.nodes.builtin.base.printer.IntegerVectorPrinter; +import com.oracle.truffle.r.nodes.builtin.base.printer.LogicalVectorPrinter; +import com.oracle.truffle.r.nodes.builtin.base.printer.PrintParameters; import com.oracle.truffle.r.nodes.builtin.base.printer.ValuePrinterNode; import com.oracle.truffle.r.nodes.unary.CastIntegerNode; import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RLogical; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; @@ -43,141 +44,144 @@ import com.oracle.truffle.r.runtime.env.REnvironment; @SuppressWarnings("unused") @RBuiltin(name = "format", kind = INTERNAL, parameterNames = {"x", "trim", "digits", "nsmall", "width", "justify", "na.encode", "scientific", "decimal.mark"}, behavior = PURE) -public abstract class Format extends RBuiltinNode { +public abstract class Format extends RBuiltinNode.Arg9 { @Child private CastIntegerNode castInteger; @Child protected ValuePrinterNode valuePrinter = new ValuePrinterNode(); - protected final BranchProfile errorProfile = BranchProfile.create(); - - public static final int R_MAX_DIGITS_OPT = 22; public static final int R_MIN_DIGITS_OPT = 0; + public static final int R_MAX_DIGITS_OPT = 22; - private static Config printConfig; - - private static Config setPrintDefaults() { - if (printConfig == null) { - printConfig = new Config(); - } - printConfig.width = (int) RContext.getInstance().stateROptions.getValue("width"); - printConfig.naWidth = RRuntime.STRING_NA.length(); - printConfig.naWidthNoQuote = RRuntime.NA_HEADER.length(); - printConfig.digits = 7 /* default */; - printConfig.scipen = 0 /* default */; - printConfig.gap = 1; - printConfig.quote = 1; - printConfig.right = Adjustment.LEFT; - printConfig.max = 99999 /* default */; - printConfig.naString = RRuntime.STRING_NA; - printConfig.naStringNoQuote = RRuntime.NA_HEADER; - printConfig.useSource = 8 /* default */; - printConfig.cutoff = 60; - return printConfig; - } - - private static Config getConfig() { - return setPrintDefaults(); - } + public static final int JUSTIFY_LEFT = 0; + public static final int JUSTIFY_RIGHT = 1; + public static final int JUSTIFY_CENTER = 2; + public static final int JUSTIFY_NONE = 3; private RAbstractIntVector castInteger(Object operand) { if (castInteger == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); castInteger = insert(CastIntegerNodeGen.create(true, false, false)); } - return (RAbstractIntVector) castInteger.execute(operand); + return (RAbstractIntVector) castInteger.doCast(operand); } static { Casts casts = new Casts(Format.class); casts.arg("x"); - casts.arg("trim").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).notNA().map(toBoolean()); + casts.arg("trim").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).mustNotBeNA().map(toBoolean()); casts.arg("digits").asIntegerVector().findFirst(RRuntime.INT_NA).mustBe(intNA().or(gte(R_MIN_DIGITS_OPT).and(lte(R_MAX_DIGITS_OPT)))); casts.arg("nsmall").asIntegerVector().findFirst(RRuntime.INT_NA).mustBe(intNA().or(gte(0).and(lte(20)))); - casts.arg("width").asIntegerVector().findFirst(0).notNA(); - casts.arg("justify").asIntegerVector().findFirst(RRuntime.INT_NA).mustBe(intNA().or(gte(0).and(lte(3)))); - casts.arg("na.encode").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).notNA().map(toBoolean()); + casts.arg("width").asIntegerVector().findFirst(0).mustNotBeNA(); + casts.arg("justify").asIntegerVector().findFirst(RRuntime.INT_NA).mustBe(intNA().or(gte(JUSTIFY_LEFT).and(lte(JUSTIFY_NONE)))); + casts.arg("na.encode").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).mustNotBeNA().map(toBoolean()); casts.arg("scientific").asIntegerVector().findFirst(); casts.arg("decimal.mark").asStringVector().findFirst(); } - @Specialization - protected RStringVector format(RAbstractLogicalVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, - String decimalMark) { - return (RStringVector) valuePrinter.prettyPrint(value, AnyVectorToStringVectorWriter::new); - } - - @Specialization - protected RStringVector format(RAbstractIntVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, - String decimalMark) { - return (RStringVector) valuePrinter.prettyPrint(value, AnyVectorToStringVectorWriter::new); + private static char getDecimalMark(String decimalMark) { + return decimalMark.length() == 0 ? '.' : decimalMark.charAt(0); } - // TODO: even though format's arguments are not used at this point, their processing mirrors - // what GNU R does - - private int computeSciArg(RAbstractVector sciVec) { - assert sciVec.getLength() > 0; - int tmp = castInteger(sciVec).getDataAt(0); - int ret; - if (sciVec.getElementClass() == RLogical.class) { - if (RRuntime.isNA(tmp)) { - ret = tmp; - } else { - ret = tmp > 0 ? -100 : 100; - } - } else { - ret = tmp; + private static PrintParameters getParameters(int digits, int scientific) { + PrintParameters pp = new PrintParameters(); + pp.setDefaults(); + if (!RRuntime.isNA(digits)) { + pp.setDigits(digits); } - if (!RRuntime.isNA(ret)) { - getConfig().scipen = ret; + if (!RRuntime.isNA(scientific)) { + pp.setScipen(scientific); } - return ret; + return pp; + } + + private static RStringVector createResult(RAbstractVector value, String[] array) { + RStringVector result = RDataFactory.createStringVector(array, value.isComplete(), value.getDimensions(), value.getNames()); + result.setDimNames(value.getDimNames()); + return result; } @Specialization - protected RStringVector format(RAbstractDoubleVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, - String decimalMark) { - return (RStringVector) valuePrinter.prettyPrint(value, AnyVectorToStringVectorWriter::new); + @TruffleBoundary + protected RStringVector format(RAbstractLogicalVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, String decimalMark) { + String[] result = LogicalVectorPrinter.format(value, trim, width, getParameters(digits, scientific)); + return createResult(value, result); } @Specialization - protected RStringVector format(RAbstractComplexVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, - String decimalMark) { - return (RStringVector) valuePrinter.prettyPrint(value, AnyVectorToStringVectorWriter::new); + @TruffleBoundary + protected RStringVector format(RAbstractIntVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, String decimalMark) { + String[] result = IntegerVectorPrinter.format(value, trim, width, getParameters(digits, scientific)); + return createResult(value, result); } @Specialization - protected RStringVector format(REnvironment value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, - String decimalMark) { - return RDataFactory.createStringVector(value.getPrintName()); + @TruffleBoundary + protected RStringVector format(RAbstractDoubleVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, String decimalMark) { + String[] result = DoubleVectorPrinter.format(value, trim, nsmall, width, getDecimalMark(decimalMark), getParameters(digits, scientific)); + return createResult(value, result); } @Specialization - protected RStringVector format(RAbstractStringVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, String decimalMark) { - // TODO: implement full semantics - return value.materialize(); + @TruffleBoundary + protected RStringVector format(RAbstractComplexVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, String decimalMark) { + String[] result = ComplexVectorPrinter.format(value, trim, nsmall, width, getDecimalMark(decimalMark), getParameters(digits, scientific)); + return createResult(value, result); } - private static class Config { - public int width; - public int naWidth; - public int naWidthNoQuote; - public int digits; - public int scipen; - public int gap; - public int quote; - public Adjustment right; - public int max; - public String naString; - public String naStringNoQuote; - public int useSource; - public int cutoff; + @Specialization + protected RStringVector format(REnvironment value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, String decimalMark) { + return RDataFactory.createStringVector(value.getPrintName()); } - private enum Adjustment { - LEFT, - RIGHT, - CENTRE, - NONE; + @Specialization + @TruffleBoundary + protected RStringVector format(RAbstractStringVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, String decimalMark) { + PrintParameters pp = getParameters(digits, scientific); + int w; + if (justify == JUSTIFY_NONE) { + w = 0; + } else { + w = width; + for (int i = 0; i < value.getLength(); i++) { + String element = value.getDataAt(i); + if (RRuntime.isNA(element)) { + if (naEncode) { + w = Math.max(w, pp.getNaWidth()); + } + } else { + w = Math.max(w, element.length()); + } + } + } + String[] result = new String[value.getLength()]; + for (int i = 0; i < value.getLength(); i++) { + String element = value.getDataAt(i); + if (!naEncode && RRuntime.isNA(element)) { + result[i] = RRuntime.STRING_NA; + } else { + String s0; + if (RRuntime.isNA(element)) { + element = pp.getNaString(); + } + int il = element.length(); + int b = w - il; + StringBuilder str = new StringBuilder(Math.max(w, il)); + if (b > 0 && justify != JUSTIFY_LEFT) { + int b0 = (justify == JUSTIFY_CENTER) ? b / 2 : b; + for (int j = 0; j < b0; j++) { + str.append(' '); + } + b -= b0; + } + str.append(element); + if (b > 0 && justify != JUSTIFY_RIGHT) { + for (int j = 0; j < b; j++) { + str.append(' '); + } + } + result[i] = str.toString(); + } + } + return createResult(value, result); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java index b872f1187f29cf756fad56b82a38f542b7b99f37..bab1c075934a48b4b486a6b16ec598ad46f3743f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java @@ -11,37 +11,31 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.unary.CastStringNode; -import com.oracle.truffle.r.nodes.unary.CastStringNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.Round.RoundArithmetic; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RAttributable; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +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.RAbstractVector; @RBuiltin(name = "formatC", kind = INTERNAL, parameterNames = {"x", "mode", "width", "digits", "format", "flag", "i.strlen"}, behavior = PURE) -public abstract class FormatC extends RBuiltinNode { +public abstract class FormatC extends RBuiltinNode.Arg7 { - @Child private CastStringNode castStringNode; - - private RStringVector castStringVector(Object o) { - if (castStringNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castStringNode = insert(CastStringNodeGen.create(true, true, true)); - } - return (RStringVector) ((RStringVector) castStringNode.executeString(o)).copyDropAttributes(); - } + @Child private RoundArithmetic round = new RoundArithmetic(); static { Casts casts = new Casts(FormatC.class); - casts.arg("x"); + casts.arg("x").mustBe(integerValue().or(doubleValue()), Message.UNSUPPORTED_TYPE); casts.arg("mode").asStringVector().findFirst(); casts.arg("width").asIntegerVector().findFirst(); casts.arg("digits").asIntegerVector().findFirst(); @@ -50,12 +44,154 @@ public abstract class FormatC extends RBuiltinNode { casts.arg("i.strlen").asIntegerVector().findFirst(); } - @SuppressWarnings("unused") @Specialization - RAttributable formatC(RAbstractContainer x, String mode, int width, int digits, String format, String flag, int iStrlen, - @Cached("create()") SetClassAttributeNode setClassAttrNode) { - RStringVector res = castStringVector(x); - setClassAttrNode.reset(res); - return res; + @TruffleBoundary + RAttributable formatC(RAbstractVector x, String mode, int width, int digits, String format, String flag, @SuppressWarnings("unused") int iStrlen) { + // ignores iStrlen + RType type = "integer".equals(mode) ? RType.Integer : RType.Double; + String[] result = strSignif(x, type, width, digits, format, flag); + return RDataFactory.createStringVector(result, true); + } + + /* + * Former src/appl/strsignif.c + * + * Copyright (C) Martin Maechler, 1994, 1998 Copyright (C) 2001-2013 the R Core Team + * + * I want you to preserve the copyright of the original author(s), and encourage you to send me + * any improvements by e-mail. (MM). + * + * Originally from Bill Dunlap bill@stat.washington.edu Wed Feb 21, 1990 + * + * Much improved by Martin Maechler, including the "fg" format. + * + * Patched by Friedrich.Leisch@ci.tuwien.ac.at Fri Nov 22, 1996 + * + * Some fixes by Ross Ihaka ihaka@stat.auckland.ac.nz Sat Dec 21, 1996 Integer arguments changed + * from "long" to "int" Bus error due to non-writable strings fixed + * + * BDR 2001-10-30 use R_alloc not Calloc as memory was not reclaimed on error (and there are + * many error exits). + * + * type "double" or "integer" (R - numeric 'mode'). + * + * width The total field width; width < 0 means to left justify the number in this field + * (equivalent to flag = "-"). It is possible that the result will be longer than this, but that + * should only happen in reasonable cases. + * + * digits The desired number of digits after the decimal point. digits < 0 uses the default for + * C, namely 6 digits. + * + * format "d" (for integers) or "f", "e","E", "g", "G" (for 'real') "f" gives numbers in the + * usual "xxx.xxx" format; "e" and "E" give n.ddde<nn> or n.dddE<nn> (scientific format); "g" + * and "G" puts them into scientific format if it saves space to do so. NEW: "fg" gives numbers + * in "xxx.xxx" format as "f", ~~ however, digits are *significant* digits and, if digits > 0, + * no trailing zeros are produced, as in "g". + * + * flag Format modifier as in K&R "C", 2nd ed., p.243; e.g., "0" pads leading zeros; "-" does + * left adjustment the other possible flags are "+", " ", and "#". New (Feb.98): if flag has + * more than one character, all are passed.. + */ + + private String[] strSignif(RAbstractVector x, RType type, int width, int digits, String format, String flag) { + int dig = Math.abs(digits); + boolean rmTrailing0 = digits >= 0; + boolean doFg = "fg".equals(format); /* TRUE iff format == "fg" */ + + if (width == 0) { + throw error(Message.GENERIC, "width cannot be zero"); + } + + String[] result = new String[x.getLength()]; + if ("d".equals(format)) { + String form = "%" + flag + width + "d"; + if (type == RType.Integer) { + for (int i = 0; i < x.getLength(); i++) { + result[i] = String.format(form, x.getDataAtAsObject(i)); + } + } else { + throw error(Message.GENERIC, "'type' must be \"integer\" for \"d\"-format"); + } + } else { /* --- floating point --- */ + + if (type == RType.Double) { + if (doFg) { /* do smart "f" : */ + for (int i = 0; i < x.getLength(); i++) { + double xx = ((RAbstractDoubleVector) x).getDataAt(i); + if (xx == 0.) { + result[i] = "0"; + } else { + /* + * This was iex= (int)floor(log10(fabs(xx))) That's wrong, as xx might + * get rounded up, and we do need some fuzz or 99.5 is correct. + */ + double xxx = Math.abs(xx); + int iex = (int) Math.floor(Math.log10(xxx) + 1e-12); + double scaledX = round.opd(xxx / Math.pow(10, iex) + 1e-12, dig - 1); + if (iex > 0 && scaledX >= 10) { + xx = scaledX * Math.pow(10, iex); + iex++; + } + if (iex == -4 && Math.abs(xx) < 1e-4) { + /* VERY rare case */ + iex = -5; + } + if (iex < -4) { + /* "g" would result in 'e-' representation: */ + String form = "%" + flag + "." + (dig - 1 + -iex) + "f"; + String str = String.format(form, xx); + /* Remove trailing "0"s __ IFF flag has no '#': */ + if (rmTrailing0) { + int j = str.length(); + while (j > 0 && str.charAt(j - 1) == '0') { + j--; + } + if (j != str.length()) { + str = str.substring(0, j); + } + } + result[i] = str; + } else { /* iex >= -4: NOT "e-" */ + /* if iex >= dig, would have "e+" representation */ + String formatString = "%" + flag + width + "." + ((iex >= dig) ? (iex + 1) : dig) + "g"; + result[i] = trimZero(String.format(formatString, xx)); + } + } /* xx != 0 */ + } /* if(do_fg) for(i..) */ + } else { + String form = "%" + flag + width + "." + dig + format; + for (int i = 0; i < x.getLength(); i++) { + String str = String.format(form, x.getDataAtAsObject(i)); + result[i] = ("g".equals(format) || "f".equals(format)) ? trimZero(str) : str; + } + } + } else { + throw error(Message.GENERIC, "'type' must be \"real\" for this format"); + } + } + return result; + } + + private static String trimZero(String str) { + int i = str.length(); + while (i > 0 && str.charAt(i - 1) == '0') { + i--; + } + if (i > 0 && str.charAt(i - 1) == '.') { + i--; + return str.substring(0, i); + } + if (i == str.length()) { + return str; + } + // need to check whether we're after the decimal point: + int j = i; + while (j > 0 && str.charAt(j - 1) >= '0' && str.charAt(j) <= '9') { + j--; + } + if (j > 0 && str.charAt(j - 1) == '.') { + return str.substring(0, i); + } + return str; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java index 109ff35ab3afc3574385174926eee5f95bf7ab74..45721e4ced626d59066cacbce3529fe5d056a3b2 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java @@ -77,7 +77,9 @@ import com.oracle.truffle.r.runtime.data.RPairList; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RPromise.Closure; import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @@ -90,17 +92,20 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; */ public class FrameFunctions { - public abstract static class FrameHelper extends RBuiltinNode { + public static final class FrameHelper extends RBaseNode { private final ConditionProfile currentFrameProfile = ConditionProfile.createBinaryProfile(); - protected final BranchProfile errorProfile = BranchProfile.create(); /** * Determine the frame access mode of a subclass. The rule of thumb is that subclasses that * only use the frame internally should not materialize it, i.e., they should use * {@link FrameAccess#READ_ONLY} or {@link FrameAccess#READ_WRITE}. */ - protected abstract FrameAccess frameAccess(); + private final FrameAccess access; + + public FrameHelper(FrameAccess access) { + this.access = access; + } protected Frame getFrame(VirtualFrame frame, int n) { int actualFrame = decodeFrameNumber(RArguments.getCall(frame), n); @@ -134,14 +139,12 @@ public class FrameFunctions { int depth = call.getDepth(); if (n > 0) { if (n > depth) { - errorProfile.enter(); - throw RError.error(RError.SHOW_CALLER, RError.Message.NOT_THAT_MANY_FRAMES); + throw error(RError.Message.NOT_THAT_MANY_FRAMES); } return n; } else { if (-n > depth) { - errorProfile.enter(); - throw RError.error(RError.SHOW_CALLER, RError.Message.NOT_THAT_MANY_FRAMES); + throw error(RError.Message.NOT_THAT_MANY_FRAMES); } return depth + n; } @@ -164,7 +167,7 @@ public class FrameFunctions { } notifyRCallNodes(actualFrame, RArguments.getCall(frame)); } - return Utils.getStackFrame(frameAccess(), actualFrame); + return Utils.getStackFrame(access, actualFrame); } } @@ -184,18 +187,15 @@ public class FrameFunctions { } @RBuiltin(name = "sys.call", kind = INTERNAL, parameterNames = {"which"}, behavior = COMPLEX) - public abstract static class SysCall extends FrameHelper { + public abstract static class SysCall extends RBuiltinNode.Arg1 { + + @Child private FrameHelper helper = new FrameHelper(FrameAccess.READ_ONLY); static { Casts casts = new Casts(SysCall.class); casts.arg("which").asIntegerVector().findFirst(); } - @Override - protected final FrameAccess frameAccess() { - return FrameAccess.READ_ONLY; - } - @Specialization protected Object sysCall(VirtualFrame frame, int which) { /* @@ -206,7 +206,7 @@ public class FrameFunctions { @TruffleBoundary private Object createCall(RCaller currentCall, int which) { - RCaller call = getCall(currentCall, which); + RCaller call = helper.getCall(currentCall, which); assert !call.isPromise(); if (call == null || !call.isValidCaller()) { return RNull.instance; @@ -230,12 +230,9 @@ public class FrameFunctions { * using "..." that make the code a lot more complex that it seems it ought to be. */ @RBuiltin(name = "match.call", kind = INTERNAL, parameterNames = {"definition", "call", "expand.dots", "envir"}, behavior = COMPLEX) - public abstract static class MatchCall extends FrameHelper { + public abstract static class MatchCall extends RBuiltinNode.Arg4 { - @Override - protected final FrameAccess frameAccess() { - return FrameAccess.READ_ONLY; - } + @Child private FrameHelper helper = new FrameHelper(FrameAccess.READ_ONLY); static { Casts casts = new Casts(MatchCall.class); @@ -253,7 +250,7 @@ public class FrameFunctions { */ RLanguage call = checkCall(callObj); if (expandDotsL == RRuntime.LOGICAL_NA) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "expand.dots"); + throw error(RError.Message.INVALID_ARGUMENT, "expand.dots"); } boolean expandDots = RRuntime.fromLogical(expandDotsL); @@ -277,7 +274,7 @@ public class FrameFunctions { ArrayList<String> names = new ArrayList<>(); FrameSlot varArgSlot = cframe.getFrameDescriptor().findFrameSlot(ArgumentsSignature.VARARG_NAME); - RArgsValuesAndNames varArgParameter = varArgSlot == null ? null : (RArgsValuesAndNames) cframe.getValue(varArgSlot); + RArgsValuesAndNames varArgParameter = varArgSlot == null ? null : (RArgsValuesAndNames) FrameSlotChangeMonitor.getValue(varArgSlot, cframe); for (int i = 0; i < sig.getLength(); i++) { RNode arg = matchedArgNodes[i]; @@ -384,7 +381,7 @@ public class FrameFunctions { @Specialization @SuppressWarnings("unused") protected RLanguage matchCall(Object definition, Object call, Object expandDots, Object envir) { - throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); + throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); } private RLanguage checkCall(Object obj) throws RError { @@ -399,12 +396,12 @@ public class FrameFunctions { return call; } } - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "call"); + throw error(RError.Message.INVALID_ARGUMENT, "call"); } } @RBuiltin(name = "sys.nframe", kind = INTERNAL, parameterNames = {}, behavior = COMPLEX) - public abstract static class SysNFrame extends RBuiltinNode { + public abstract static class SysNFrame extends RBuiltinNode.Arg0 { private final BranchProfile isPromiseCurrentProfile = BranchProfile.create(); private final BranchProfile isPromiseResultProfile = BranchProfile.create(); @@ -425,13 +422,11 @@ public class FrameFunctions { } } - private abstract static class DeoptHelper extends FrameHelper { - protected final PromiseDeoptimizeFrameNode deoptFrameNode = new PromiseDeoptimizeFrameNode(); - - } - @RBuiltin(name = "sys.frame", kind = INTERNAL, parameterNames = {"which"}, behavior = COMPLEX) - public abstract static class SysFrame extends DeoptHelper { + public abstract static class SysFrame extends RBuiltinNode.Arg1 { + + @Child private FrameHelper helper = new FrameHelper(FrameAccess.MATERIALIZE); + @Child private PromiseDeoptimizeFrameNode deoptFrameNode = new PromiseDeoptimizeFrameNode(); private final ConditionProfile zeroProfile = ConditionProfile.createBinaryProfile(); @@ -441,11 +436,6 @@ public class FrameFunctions { return SysFrameNodeGen.create(); } - @Override - protected final FrameAccess frameAccess() { - return FrameAccess.MATERIALIZE; - } - static { Casts casts = new Casts(SysFrame.class); casts.arg("which").asIntegerVector().findFirst(); @@ -457,23 +447,21 @@ public class FrameFunctions { if (zeroProfile.profile(which == 0)) { result = REnvironment.globalEnv(); } else { - Frame callerFrame = getFrame(frame, which); + Frame callerFrame = helper.getFrame(frame, which); result = REnvironment.frameToEnvironment(callerFrame.materialize()); } // Deoptimize every promise which is now in this frame, as it might leave it's stack deoptFrameNode.deoptimizeFrame(result.getFrame()); - return result; } } @RBuiltin(name = "sys.frames", kind = INTERNAL, parameterNames = {}, behavior = COMPLEX) - public abstract static class SysFrames extends DeoptHelper { - @Override - protected final FrameAccess frameAccess() { - return FrameAccess.MATERIALIZE; - } + public abstract static class SysFrames extends RBuiltinNode.Arg0 { + + @Child private FrameHelper helper = new FrameHelper(FrameAccess.MATERIALIZE); + @Child private PromiseDeoptimizeFrameNode deoptFrameNode = new PromiseDeoptimizeFrameNode(); @Specialization protected Object sysFrames(VirtualFrame frame) { @@ -484,7 +472,7 @@ public class FrameFunctions { RPairList result = RDataFactory.createPairList(); RPairList next = result; for (int i = 1; i < depth; i++) { - MaterializedFrame mf = getNumberedFrame(frame, i).materialize(); + MaterializedFrame mf = helper.getNumberedFrame(frame, i).materialize(); deoptFrameNode.deoptimizeFrame(mf); next.setCar(REnvironment.frameToEnvironment(mf)); if (i != depth - 1) { @@ -501,12 +489,7 @@ public class FrameFunctions { } @RBuiltin(name = "sys.calls", kind = INTERNAL, parameterNames = {}, behavior = COMPLEX) - public abstract static class SysCalls extends FrameHelper { - - @Override - protected final FrameAccess frameAccess() { - return FrameAccess.READ_ONLY; - } + public abstract static class SysCalls extends RBuiltinNode.Arg0 { @Specialization protected Object sysCalls(VirtualFrame frame) { @@ -548,7 +531,7 @@ public class FrameFunctions { } @RBuiltin(name = "sys.parent", kind = INTERNAL, parameterNames = {"n"}, behavior = COMPLEX) - public abstract static class SysParent extends RBuiltinNode { + public abstract static class SysParent extends RBuiltinNode.Arg1 { private final BranchProfile nullCallerProfile = BranchProfile.create(); private final BranchProfile promiseProfile = BranchProfile.create(); @@ -579,14 +562,11 @@ public class FrameFunctions { } @RBuiltin(name = "sys.function", kind = INTERNAL, parameterNames = {"which"}, splitCaller = true, alwaysSplit = true, behavior = COMPLEX) - public abstract static class SysFunction extends FrameHelper { + public abstract static class SysFunction extends RBuiltinNode.Arg1 { - public abstract Object executeObject(VirtualFrame frame, int which); + @Child private FrameHelper helper = new FrameHelper(FrameAccess.READ_ONLY); - @Override - protected final FrameAccess frameAccess() { - return FrameAccess.READ_ONLY; - } + public abstract Object executeObject(VirtualFrame frame, int which); static { Casts casts = new Casts(SysFunction.class); @@ -596,7 +576,7 @@ public class FrameFunctions { @Specialization protected Object sysFunction(VirtualFrame frame, int which) { // N.B. Despite the spec, n==0 is treated as the current function - Frame callerFrame = getFrame(frame, which); + Frame callerFrame = helper.getFrame(frame, which); RFunction func = RArguments.getFunction(callerFrame); if (func == null) { @@ -608,12 +588,7 @@ public class FrameFunctions { } @RBuiltin(name = "sys.parents", kind = INTERNAL, parameterNames = {}, behavior = COMPLEX) - public abstract static class SysParents extends FrameHelper { - - @Override - protected final FrameAccess frameAccess() { - return FrameAccess.READ_ONLY; - } + public abstract static class SysParents extends RBuiltinNode.Arg0 { @Specialization protected RIntVector sysParents(VirtualFrame frame) { @@ -652,7 +627,9 @@ public class FrameFunctions { * The environment of the caller of the function that called parent.frame. */ @RBuiltin(name = "parent.frame", kind = SUBSTITUTE, parameterNames = {"n"}, behavior = COMPLEX) - public abstract static class ParentFrame extends FrameHelper { + public abstract static class ParentFrame extends RBuiltinNode.Arg1 { + + @Child private FrameHelper helper = new FrameHelper(FrameAccess.MATERIALIZE); private final BranchProfile nullCallerProfile = BranchProfile.create(); private final BranchProfile promiseProfile = BranchProfile.create(); @@ -670,11 +647,6 @@ public class FrameFunctions { return new Object[]{1}; } - @Override - protected final FrameAccess frameAccess() { - return FrameAccess.MATERIALIZE; - } - @Specialization(guards = "n == 1") protected REnvironment parentFrameDirect(VirtualFrame frame, @SuppressWarnings("unused") int n, @Cached("new()") GetCallerFrameNode getCaller) { @@ -684,8 +656,7 @@ public class FrameFunctions { @Specialization(replaces = "parentFrameDirect") protected REnvironment parentFrame(VirtualFrame frame, int n) { if (n <= 0) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_VALUE, "n"); + throw error(RError.Message.INVALID_VALUE, "n"); } RCaller call = RArguments.getCall(frame); while (call.isPromise()) { @@ -712,7 +683,7 @@ public class FrameFunctions { // */ // parentDepth--; // } - return REnvironment.frameToEnvironment(getNumberedFrame(frame, call.getDepth()).materialize()); + return REnvironment.frameToEnvironment(helper.getNumberedFrame(frame, call.getDepth()).materialize()); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Gc.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Gc.java index ad8d21132c6fc067f75dc68ed45e317711fd6812..7a5326f06608a25a8f20b628016429db2a2d38aa 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Gc.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Gc.java @@ -28,7 +28,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import java.util.Arrays; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RRuntime; @@ -37,7 +36,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDoubleVector; @RBuiltin(name = "gc", kind = INTERNAL, parameterNames = {"verbose", "reset"}, behavior = COMPLEX) -public abstract class Gc extends RBuiltinNode { +public abstract class Gc extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(Gc.class); @@ -48,15 +47,13 @@ public abstract class Gc extends RBuiltinNode { @SuppressWarnings("unused") @Specialization protected RDoubleVector gc(boolean verbose, boolean reset) { - doGc(); + /* + * It is rarely advisable to actually force a gc in Java, therefore we simply ignore this + * builtin. + */ // TODO: somehow produce the (semi?) correct values double[] data = new double[14]; Arrays.fill(data, RRuntime.DOUBLE_NA); return RDataFactory.createDoubleVector(data, RDataFactory.INCOMPLETE_VECTOR); } - - @TruffleBoundary - private static void doGc() { - System.gc(); - } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetClass.java index 2a2ddedc86d4c3646e9a1e66ae271b6ab961dc78..62e9ca8f725537af09f60666ce0fd99ca7b3ddcf 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetClass.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetClass.java @@ -21,7 +21,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "class", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) -public abstract class GetClass extends RBuiltinNode { +public abstract class GetClass extends RBuiltinNode.Arg1 { @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(true, false); 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 cae0c2dcee59304515f6848f2c2bed44e1aadd12..a05fba7d0a78b52737beb2200532f51fb97e55e3 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 @@ -41,7 +41,6 @@ import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.RRootNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.attributes.TypeFromModeNode; @@ -73,26 +72,27 @@ import com.oracle.truffle.r.runtime.data.RS4Object; 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; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; /** * assert: not expected to be fast even when called as, e.g., {@code get("x")}. */ public class GetFunctions { - public abstract static class Adapter extends RBuiltinNode { - private final BranchProfile unknownObjectErrorProfile = BranchProfile.create(); - protected final ValueProfile modeProfile = ValueProfile.createIdentityProfile(); + private static final class Helper extends RBaseNode { + protected final BranchProfile recursiveProfile = BranchProfile.create(); + @Child private PromiseHelperNode promiseHelper = new PromiseHelperNode(); @Child protected TypeFromModeNode typeFromMode = TypeFromModeNodeGen.create(); @CompilationFinal private boolean firstExecution = true; protected void unknownObject(String x, RType modeType, String modeString) throws RError { - unknownObjectErrorProfile.enter(); + CompilerDirectives.transferToInterpreter(); if (modeType == RType.Any) { - throw RError.error(RError.SHOW_CALLER, RError.Message.UNKNOWN_OBJECT, x); + throw error(RError.Message.UNKNOWN_OBJECT, x); } else { - throw RError.error(RError.SHOW_CALLER, RError.Message.UNKNOWN_OBJECT_MODE, x, modeType == null ? modeString : modeType.getName()); + throw error(RError.Message.UNKNOWN_OBJECT_MODE, x, modeType == null ? modeString : modeType.getName()); } } @@ -161,11 +161,13 @@ public class GetFunctions { } @RBuiltin(name = "get", kind = INTERNAL, parameterNames = {"x", "envir", "mode", "inherits"}, behavior = COMPLEX) - public abstract static class Get extends Adapter { + public abstract static class Get extends RBuiltinNode.Arg4 { + + @Child private Helper helper = new Helper(); private final ConditionProfile inheritsProfile = ConditionProfile.createBinaryProfile(); - public abstract Object execute(VirtualFrame frame, String x, REnvironment environment, String mode, boolean inherits); + public abstract Object execute(VirtualFrame frame, Object what, Object where, String name, boolean inherits); static { Casts casts = new Casts(Get.class); @@ -178,11 +180,11 @@ public class GetFunctions { @Specialization public Object get(VirtualFrame frame, String x, REnvironment envir, String mode, boolean inherits) { - RType modeType = typeFromMode.execute(mode); + RType modeType = helper.typeFromMode.execute(mode); if (inheritsProfile.profile(inherits)) { - return getInherits(frame, x, envir, modeType, mode, true); + return helper.getInherits(frame, x, envir, modeType, mode, true); } else { - return getAndCheck(frame, x, envir, modeType, mode, true); + return helper.getAndCheck(frame, x, envir, modeType, mode, true); } } @@ -197,10 +199,13 @@ public class GetFunctions { protected Object get(VirtualFrame frame, String x, int envir, String mode, boolean inherits) { throw RInternalError.unimplemented(); } + } @RBuiltin(name = "get0", kind = INTERNAL, parameterNames = {"x", "envir", "mode", "inherits", "ifnotfound"}, behavior = COMPLEX) - public abstract static class Get0 extends Adapter { + public abstract static class Get0 extends RBuiltinNode.Arg5 { + + @Child private Helper helper = new Helper(); private final ConditionProfile inheritsProfile = ConditionProfile.createBinaryProfile(); @@ -216,11 +221,11 @@ public class GetFunctions { @Specialization protected Object get0(VirtualFrame frame, String x, REnvironment envir, String mode, boolean inherits, Object ifnotfound) { Object result; - RType modeType = typeFromMode.execute(mode); + RType modeType = helper.typeFromMode.execute(mode); if (inheritsProfile.profile(inherits)) { - result = getInherits(frame, x, envir, modeType, mode, false); + result = helper.getInherits(frame, x, envir, modeType, mode, false); } else { - result = getAndCheck(frame, x, envir, modeType, mode, false); + result = helper.getAndCheck(frame, x, envir, modeType, mode, false); } if (result == null) { result = ifnotfound; @@ -242,7 +247,9 @@ public class GetFunctions { } @RBuiltin(name = "mget", kind = INTERNAL, parameterNames = {"x", "envir", "mode", "ifnotfound", "inherits"}, behavior = COMPLEX) - public abstract static class MGet extends Adapter { + public abstract static class MGet extends RBuiltinNode.Arg5 { + + @Child private Helper helper = new Helper(); private final BranchProfile wrongLengthErrorProfile = BranchProfile.create(); @@ -254,8 +261,7 @@ public class GetFunctions { static { Casts casts = new Casts(MGet.class); casts.arg("x").mustBe(stringValue()).asStringVector(); - casts.arg("envir").mustBe(instanceOf(REnvironment.class).or(integerValue()).or(doubleValue()).or(instanceOf(RS4Object.class))).mapIf(integerValue().or(doubleValue()), - chain(asIntegerVector()).with(findFirst().integerElement()).end()); + casts.arg("envir").mustBe(instanceOf(REnvironment.class).or(instanceOf(RS4Object.class)), RError.Message.MUST_BE_ENVIRON2, "second argument"); casts.arg("mode").mustBe(stringValue()).asStringVector(); casts.arg("ifnotfound").mustBe(RAbstractListVector.class); casts.arg("inherits").asLogicalVector().findFirst().map(toBoolean()); @@ -299,11 +305,11 @@ public class GetFunctions { State state = new State(xv, mode, ifNotFound); if (!(state.modeLength == 1 || state.modeLength == state.svLength)) { wrongLengthErrorProfile.enter(); - throw RError.error(this, RError.Message.WRONG_LENGTH_ARG, "mode"); + throw error(RError.Message.WRONG_LENGTH_ARG, "mode"); } if (!(state.ifNotFoundLength == 1 || state.ifNotFoundLength == state.svLength)) { wrongLengthErrorProfile.enter(); - throw RError.error(this, RError.Message.WRONG_LENGTH_ARG, "ifnotfound"); + throw error(RError.Message.WRONG_LENGTH_ARG, "ifnotfound"); } return state; } @@ -319,12 +325,12 @@ public class GetFunctions { if (inheritsProfile.profile(inherits)) { Object r = envir.get(x); if (r == null || !RRuntime.checkType(r, modeType)) { - recursiveProfile.enter(); + helper.recursiveProfile.enter(); REnvironment env = envir; while (env != REnvironment.emptyEnv()) { env = env.getParent(); if (env != REnvironment.emptyEnv()) { - r = checkPromise(frame, env.get(x), x); + r = helper.checkPromise(frame, env.get(x), x); if (r != null && RRuntime.checkType(r, modeType)) { break; } @@ -337,7 +343,7 @@ public class GetFunctions { state.data[i] = r; } } else { - Object r = checkPromise(frame, envir.get(x), x); + Object r = helper.checkPromise(frame, envir.get(x), x); if (r != null && RRuntime.checkType(r, modeType)) { state.data[i] = r; } else { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetOldClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetOldClass.java index 374a9e866f1f6a004bdfea7e950ce74fc0a9d4ca..8301704079762b789c5b79c3d1395fd6e5680ea8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetOldClass.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetOldClass.java @@ -25,17 +25,19 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetClassAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; @RBuiltin(name = "oldClass", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) -public abstract class GetOldClass extends RBuiltinNode { +public abstract class GetOldClass extends RBuiltinNode.Arg1 { private final ConditionProfile isObjectProfile = ConditionProfile.createBinaryProfile(); @Child private GetClassAttributeNode getClassNode = GetClassAttributeNode.create(); @@ -45,9 +47,10 @@ public abstract class GetOldClass extends RBuiltinNode { } @Specialization - protected Object getOldClass(RAbstractContainer arg) { + protected Object getOldClass(RAbstractContainer arg, + @Cached("createWithImplicit()") ClassHierarchyNode hierarchy) { if (isObjectProfile.profile(getClassNode.isObject(arg))) { - return arg.getClassHierarchy(); + return hierarchy.execute(arg); } else { return RNull.instance; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java index 32583e1a76f101e2d4245db0411b2c3e814297df..6368703c0f9698b69587643ea00236e65d394b5c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java @@ -27,17 +27,18 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "gettext", kind = INTERNAL, parameterNames = {"domain", "args"}, behavior = PURE) -public abstract class GetText extends RBuiltinNode { +public abstract class GetText extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(GetText.class); casts.arg("domain").asStringVector().findFirst(""); - casts.arg("args").asStringVector(); + casts.arg("args").mustNotBeMissing(Message.ARGUMENT_EMPTY, 2).asStringVector(); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Getwd.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Getwd.java index 1e5ab0b3745b9f0e3134bd0d4c8857ab05fc4cc7..c8244e9b43e119641fcfe61092aaede81f6c5d26 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Getwd.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Getwd.java @@ -33,7 +33,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.ffi.BaseRFFI; @RBuiltin(name = "getwd", kind = INTERNAL, parameterNames = {}, behavior = IO) -public abstract class Getwd extends RBuiltinNode { +public abstract class Getwd extends RBuiltinNode.Arg0 { @Child private BaseRFFI.GetwdNode getwdNode = BaseRFFI.GetwdNode.create(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java index 2f45bf6836886d361715191b1a1da808950653a1..97a8bf4feb5d6453fc18ebd75632b2a955f4bff1 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java @@ -11,8 +11,12 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -25,9 +29,14 @@ import java.util.regex.PatternSyntaxException; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.nodes.NodeCost; +import com.oracle.truffle.api.nodes.NodeInfo; import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode; +import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; @@ -44,6 +53,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.ffi.PCRERFFI; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.ops.na.NACheck; /** @@ -62,51 +72,58 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; * Parts of this code, notably the perl support, were translated from GnuR grep.c. */ public class GrepFunctions { - public abstract static class CommonCodeAdapter extends RBuiltinNode { - @Child protected PCRERFFI.MaketablesNode maketablesNode = RFFIFactory.getRFFI().getPCRERFFI().createMaketablesNode(); - @Child protected PCRERFFI.CompileNode compileNode = RFFIFactory.getRFFI().getPCRERFFI().createCompileNode(); + protected static void castPattern(Casts casts) { + // with default error message, NO_CALLER does not work + casts.arg("pattern").mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, "pattern").asVector().mustBe(notEmpty(), RError.Message.INVALID_ARGUMENT, + "pattern"); + } - protected static void castPattern(Casts casts) { - // with default error message, NO_CALLER does not work - casts.arg("pattern").mustBe(stringValue(), RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "pattern").asVector().mustBe(notEmpty(), RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, - "pattern"); - } + protected static void castPatternSingle(Casts casts) { + // with default error message, NO_CALLER does not work + casts.arg("pattern").mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, "pattern").asVector().mustBe(notEmpty(), RError.Message.INVALID_ARGUMENT, + "pattern").shouldBe(singleElement(), RError.Message.ARGUMENT_ONLY_FIRST, "pattern").findFirst(); + } - protected static void castText(Casts casts, String textId) { - casts.arg(textId).mustBe(stringValue(), RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, textId); - } + protected static void castText(Casts casts, String textId) { + casts.arg(textId).mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, textId); + } - protected static void castIgnoreCase(Casts casts) { - casts.arg("ignore.case").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); - } + protected static void castIgnoreCase(Casts casts) { + casts.arg("ignore.case").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); + } - protected static void castPerl(Casts casts) { - casts.arg("perl").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); - } + protected static void castPerl(Casts casts) { + casts.arg("perl").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); + } - protected static void castFixed(Casts casts, byte defaultValue) { - casts.arg("fixed").asLogicalVector().findFirst(defaultValue); - } + protected static void castFixed(Casts casts, byte defaultValue) { + casts.arg("fixed").asLogicalVector().findFirst(defaultValue).map(toBoolean()); + } - protected static void castValue(Casts casts) { - casts.arg("value").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); - } + protected static void castValue(Casts casts) { + casts.arg("value").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); + } - protected static void castUseBytes(Casts casts) { - casts.arg("useBytes").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); - } + protected static void castCosts(Casts casts) { + casts.arg("costs").defaultError(RError.Message.INVALID_ARG, "costs").mustBe((missingValue().or(nullValue()).not())).asIntegerVector(); + } - protected static void castInvert(Casts casts) { - casts.arg("invert").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); - } + protected static void castUseBytes(Casts casts) { + casts.arg("useBytes").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); + } - protected static void castCosts(Casts casts) { - casts.arg("costs").asIntegerVector(); - } + protected static void castInvert(Casts casts) { + casts.arg("invert").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); + } - protected static void castBounds(Casts casts) { - casts.arg("bounds").asDoubleVector(); - } + protected static void castBounds(Casts casts) { + casts.arg("bounds").defaultError(RError.Message.INVALID_ARG, "bounds").mustBe((missingValue().or(nullValue()).not())).asDoubleVector(); + } + + @NodeInfo(cost = NodeCost.NONE) + public static class CommonCodeNode extends RBaseNode { + @Child protected PCRERFFI.MaketablesNode maketablesNode = RFFIFactory.getRFFI().getPCRERFFI().createMaketablesNode(); + @Child protected PCRERFFI.CompileNode compileNode = RFFIFactory.getRFFI().getPCRERFFI().createCompileNode(); /** * Temporary method that handles the check for the arguments that are common to the majority @@ -114,47 +131,38 @@ public class GrepFunctions { * then an NYI error will be thrown (in the first one). If any of the arguments do not * apply, pass {@link RRuntime#LOGICAL_FALSE}. */ - protected void checkExtraArgs(byte ignoreCase, byte perl, byte fixed, @SuppressWarnings("unused") byte useBytes, byte invert) { - checkNotImplemented(RRuntime.fromLogical(ignoreCase), "ignoreCase", true); - checkNotImplemented(RRuntime.fromLogical(perl), "perl", true); - checkNotImplemented(RRuntime.fromLogical(fixed), "fixed", true); + protected void checkExtraArgs(boolean ignoreCase, boolean perl, boolean fixed, @SuppressWarnings("unused") boolean useBytes, boolean invert) { + checkNotImplemented(ignoreCase, "ignoreCase", true); + checkNotImplemented(perl, "perl", true); + checkNotImplemented(fixed, "fixed", true); // We just ignore useBytes // checkNotImplemented(RRuntime.fromLogical(useBytes), "useBytes", true); - checkNotImplemented(RRuntime.fromLogical(invert), "invert", true); + checkNotImplemented(invert, "invert", true); } protected void checkCaseFixed(boolean ignoreCase, boolean fixed) { if (ignoreCase && fixed) { - RError.warning(this, RError.Message.ARGUMENT_IGNORED, "ignore.case = TRUE"); + warning(RError.Message.ARGUMENT_IGNORED, "ignore.case = TRUE"); } } protected boolean checkPerlFixed(boolean perl, boolean fixed) { if (fixed && perl) { - RError.warning(this, RError.Message.ARGUMENT_IGNORED, "perl = TRUE"); + warning(RError.Message.ARGUMENT_IGNORED, "perl = TRUE"); return false; } else { return perl; } } - protected String checkLength(RAbstractStringVector arg, String name) { - if (arg.getLength() < 1) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, name); - } else if (arg.getLength() > 1) { - RError.warning(this, RError.Message.ARGUMENT_ONLY_FIRST, name); - } - return arg.getDataAt(0); - } - /** * Temporary check for the {@code value} argument, which is only applicable to {@code grep} * and {@code agrep} (so not included in {@code checkExtraArgs}. * * @param value */ - protected void valueCheck(byte value) { - if (RRuntime.fromLogical(value)) { + protected void valueCheck(boolean value) { + if (value) { throw RError.nyi(this, "value == true"); } } @@ -180,10 +188,6 @@ public class GrepFunctions { } } - protected boolean isTrue(byte fixed) { - return RRuntime.fromLogical(fixed); - } - protected RStringVector allStringNAResult(int len) { String[] naData = new String[len]; for (int i = 0; i < len; i++) { @@ -206,32 +210,28 @@ public class GrepFunctions { PCRERFFI.Result pcre = compileNode.execute(pattern, cflags, tables); if (pcre.result == 0) { // TODO output warning if pcre.errorMessage not NULL - throw RError.error(this, RError.Message.INVALID_REGEXP, pattern); + throw error(RError.Message.INVALID_REGEXP, pattern); } return pcre; } } - private abstract static class GrepAdapter extends CommonCodeAdapter { + protected static final class GrepCommonCodeNode extends CommonCodeNode { @Child PCRERFFI.ExecNode execNode = RFFIFactory.getRFFI().getPCRERFFI().createExecNode(); - protected Object doGrep(RAbstractStringVector patternArgVec, RAbstractStringVector vector, byte ignoreCaseLogical, byte valueLogical, byte perlLogical, byte fixedLogical, - @SuppressWarnings("unused") byte useBytes, byte invertLogical, boolean grepl) { - boolean value = RRuntime.fromLogical(valueLogical); - boolean invert = RRuntime.fromLogical(invertLogical); - boolean perl = RRuntime.fromLogical(perlLogical); - boolean ignoreCase = RRuntime.fromLogical(ignoreCaseLogical); - boolean fixed = RRuntime.fromLogical(fixedLogical); - perl = checkPerlFixed(RRuntime.fromLogical(perlLogical), fixed); + protected Object doGrep(String patternArg, RAbstractStringVector vector, boolean ignoreCase, boolean value, boolean perlPar, boolean fixed, + @SuppressWarnings("unused") boolean useBytes, boolean invert, boolean grepl) { + boolean perl = perlPar; + perl = checkPerlFixed(perlPar, fixed); checkCaseFixed(ignoreCase, fixed); - String pattern = checkLength(patternArgVec, "pattern"); + String pattern = patternArg; int len = vector.getLength(); if (RRuntime.isNA(pattern)) { return value ? allStringNAResult(len) : allIntNAResult(len); } boolean[] matches = new boolean[len]; - if (fixed && !perl) { + if (!perl) { // TODO case if (!fixed) { pattern = RegExp.checkPreDefinedClasses(pattern); @@ -299,7 +299,7 @@ public class GrepFunctions { } } - protected void findAllMatches(boolean[] result, String pattern, RAbstractStringVector vector, boolean fixed, boolean ignoreCase) { + protected static void findAllMatches(boolean[] result, String pattern, RAbstractStringVector vector, boolean fixed, boolean ignoreCase) { for (int i = 0; i < result.length; i++) { String text = vector.getDataAt(i); if (!RRuntime.isNA(text)) { @@ -313,17 +313,30 @@ public class GrepFunctions { } protected static boolean findMatch(String pattern, String text, boolean ignoreCase) { - Matcher m = Regexp.getPatternMatcher(pattern, text, ignoreCase); + Matcher m = Regexpr.getPatternMatcher(pattern, text, ignoreCase); return m.find(); } } + public static CommonCodeNode createCommon() { + return new CommonCodeNode(); + } + + public static GrepCommonCodeNode createGrepCommon() { + return new GrepCommonCodeNode(); + } + + public static SubCommonCodeNode createSubCommon() { + return new SubCommonCodeNode(); + } + + @ImportStatic(GrepFunctions.class) @RBuiltin(name = "grep", kind = INTERNAL, parameterNames = {"pattern", "text", "ignore.case", "value", "perl", "fixed", "useBytes", "invert"}, behavior = PURE) - public abstract static class Grep extends GrepAdapter { + public abstract static class Grep extends RBuiltinNode.Arg8 { static { Casts casts = new Casts(Grep.class); - castPattern(casts); + castPatternSingle(casts); castText(casts, "text"); castIgnoreCase(casts); castValue(casts); @@ -333,20 +346,51 @@ public class GrepFunctions { castInvert(casts); } + protected boolean checkContains(boolean value, boolean perl, boolean fixed, boolean useBytes) { + return fixed && !useBytes && !value && !perl; + } + + @Specialization(guards = {"checkContains(value, perl, fixed, useBytes)"}) + @TruffleBoundary + protected Object grepValueFixed(String patternPar, RAbstractStringVector vector, boolean ignoreCase, @SuppressWarnings("unused") boolean value, + @SuppressWarnings("unused") boolean perl, + @SuppressWarnings("unused") boolean fixed, @SuppressWarnings("unused") boolean useBytes, boolean invert) { + + String pattern = ignoreCase ? patternPar.toLowerCase() : patternPar; + + int[] matchIndices = new int[vector.getLength()]; + int matches = 0; + for (int i = 0; i < vector.getLength(); i++) { + String s = vector.getDataAt(i); + if (ignoreCase) { + s = s.toLowerCase(); + } + + if (s.contains(pattern) == !invert) { + // don't forget: R indices are 1-based + matchIndices[matches++] = i + 1; + } + } + + return RDataFactory.createIntVector(Arrays.copyOf(matchIndices, matches), true); + } + @Specialization @TruffleBoundary - protected Object grepValueFalse(RAbstractStringVector patternArgVec, RAbstractStringVector vector, byte ignoreCaseLogical, byte valueLogical, byte perlLogical, byte fixedLogical, - byte useBytes, byte invertLogical) { - return doGrep(patternArgVec, vector, ignoreCaseLogical, valueLogical, perlLogical, fixedLogical, useBytes, invertLogical, false); + protected Object grepValueFalse(String patternArgVec, RAbstractStringVector vector, boolean ignoreCaseLogical, boolean valueLogical, boolean perlLogical, boolean fixedLogical, + boolean useBytes, boolean invertLogical, + @Cached("createGrepCommon()") GrepCommonCodeNode common) { + return common.doGrep(patternArgVec, vector, ignoreCaseLogical, valueLogical, perlLogical, fixedLogical, useBytes, invertLogical, false); } } + @ImportStatic(GrepFunctions.class) @RBuiltin(name = "grepl", kind = INTERNAL, parameterNames = {"pattern", "text", "ignore.case", "value", "perl", "fixed", "useBytes", "invert"}, behavior = PURE) - public abstract static class GrepL extends GrepAdapter { + public abstract static class GrepL extends RBuiltinNode.Arg8 { static { Casts casts = new Casts(GrepL.class); - castPattern(casts); + castPatternSingle(casts); castText(casts, "text"); castIgnoreCase(casts); castValue(casts); @@ -358,33 +402,33 @@ public class GrepFunctions { @Specialization @TruffleBoundary - protected Object grepl(RAbstractStringVector patternArgVec, RAbstractStringVector vector, byte ignoreCaseLogical, byte valueLogical, byte perlLogical, byte fixedLogical, byte useBytes, - byte invertLogical) { + protected Object grepl(String pattern, RAbstractStringVector vector, boolean ignoreCaseLogical, boolean valueLogical, boolean perlLogical, boolean fixedLogical, boolean useBytes, + boolean invertLogical, + @Cached("createGrepCommon()") GrepCommonCodeNode common) { // invert is passed but is always FALSE - return doGrep(patternArgVec, vector, ignoreCaseLogical, valueLogical, perlLogical, fixedLogical, useBytes, invertLogical, true); + return common.doGrep(pattern, vector, ignoreCaseLogical, valueLogical, perlLogical, fixedLogical, useBytes, invertLogical, true); } } - protected abstract static class SubAdapter extends CommonCodeAdapter { - @Child PCRERFFI.ExecNode execNode = RFFIFactory.getRFFI().getPCRERFFI().createExecNode(); + protected static void castReplacement(Casts casts) { + // with default error message, NO_CALLER does not work + casts.arg("replacement").mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, "replacement").asVector().mustBe(notEmpty(), RError.Message.INVALID_ARGUMENT, "replacement").shouldBe( + singleElement(), RError.Message.ARGUMENT_ONLY_FIRST, "replacement").findFirst(); + } - protected static void castReplacement(Casts casts) { - // with default error message, NO_CALLER does not work - casts.arg("replacement").mustBe(stringValue(), RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "replacement").asVector().mustBe(notEmpty(), RError.NO_CALLER, - RError.Message.INVALID_ARGUMENT, "replacement"); - } + protected static final class SubCommonCodeNode extends CommonCodeNode { + @Child PCRERFFI.ExecNode execNode = RFFIFactory.getRFFI().getPCRERFFI().createExecNode(); - protected RStringVector doSub(RAbstractStringVector patternArgVec, RAbstractStringVector replacementVec, RAbstractStringVector vector, byte ignoreCaseLogical, byte perlLogical, - byte fixedLogical, @SuppressWarnings("unused") byte useBytes, boolean gsub) { + protected RStringVector doSub(String patternArg, String replacementArg, RAbstractStringVector vector, boolean ignoreCase, boolean perlPar, + boolean fixedPar, @SuppressWarnings("unused") boolean useBytes, boolean gsub) { try { - boolean perl = RRuntime.fromLogical(perlLogical); - boolean fixed = RRuntime.fromLogical(fixedLogical); - boolean ignoreCase = RRuntime.fromLogical(ignoreCaseLogical); + boolean perl = perlPar; + boolean fixed = fixedPar; checkNotImplemented(!(perl || fixed) && ignoreCase, "ignoreCase", true); checkCaseFixed(ignoreCase, fixed); perl = checkPerlFixed(perl, fixed); - String pattern = checkLength(patternArgVec, "pattern"); - String replacement = checkLength(replacementVec, "replacement"); + String pattern = patternArg; + String replacement = replacementArg; int len = vector.getLength(); if (RRuntime.isNA(pattern)) { @@ -641,12 +685,13 @@ public class GrepFunctions { } } + @ImportStatic(GrepFunctions.class) @RBuiltin(name = "sub", kind = INTERNAL, parameterNames = {"pattern", "replacement", "text", "ignore.case", "perl", "fixed", "useBytes"}, behavior = PURE) - public abstract static class Sub extends SubAdapter { + public abstract static class Sub extends RBuiltinNode.Arg7 { static { Casts casts = new Casts(Sub.class); - castPattern(casts); + castPatternSingle(casts); castReplacement(casts); castText(casts, "text"); castIgnoreCase(casts); @@ -657,18 +702,19 @@ public class GrepFunctions { @Specialization @TruffleBoundary - protected RStringVector subRegexp(RAbstractStringVector patternArgVec, RAbstractStringVector replacementVec, RAbstractStringVector x, byte ignoreCaseLogical, byte perlLogical, - byte fixedLogical, byte useBytes) { - return doSub(patternArgVec, replacementVec, x, ignoreCaseLogical, perlLogical, fixedLogical, useBytes, false); + protected RStringVector subRegexp(String patternArgVec, String replacementVec, RAbstractStringVector x, boolean ignoreCaseLogical, boolean perlLogical, boolean fixedLogical, boolean useBytes, + @Cached("createSubCommon()") SubCommonCodeNode common) { + return common.doSub(patternArgVec, replacementVec, x, ignoreCaseLogical, perlLogical, fixedLogical, useBytes, false); } } + @ImportStatic(GrepFunctions.class) @RBuiltin(name = "gsub", kind = INTERNAL, parameterNames = {"pattern", "replacement", "text", "ignore.case", "perl", "fixed", "useBytes"}, behavior = PURE) - public abstract static class GSub extends SubAdapter { + public abstract static class GSub extends RBuiltinNode.Arg7 { static { Casts casts = new Casts(GSub.class); - castPattern(casts); + castPatternSingle(casts); castReplacement(casts); castText(casts, "text"); castIgnoreCase(casts); @@ -679,14 +725,15 @@ public class GrepFunctions { @Specialization @TruffleBoundary - protected RStringVector gsub(RAbstractStringVector patternArgVec, RAbstractStringVector replacementVec, RAbstractStringVector x, byte ignoreCaseLogical, byte perlLogical, byte fixedLogical, - byte useBytes) { - return doSub(patternArgVec, replacementVec, x, ignoreCaseLogical, perlLogical, fixedLogical, useBytes, true); + protected RStringVector gsub(String patternArgVec, String replacementVec, RAbstractStringVector x, boolean ignoreCaseLogical, boolean perlLogical, boolean fixedLogical, boolean useBytes, + @Cached("createSubCommon()") SubCommonCodeNode common) { + return common.doSub(patternArgVec, replacementVec, x, ignoreCaseLogical, perlLogical, fixedLogical, useBytes, true); } } + @ImportStatic(GrepFunctions.class) @RBuiltin(name = "regexpr", kind = INTERNAL, parameterNames = {"pattern", "text", "ignore.case", "perl", "fixed", "useBytes"}, behavior = PURE) - public abstract static class Regexp extends CommonCodeAdapter { + public abstract static class Regexpr extends RBuiltinNode.Arg6 { @Child SetFixedAttributeNode setMatchLengthAttrNode = SetFixedAttributeNode.create("match.length"); @Child SetFixedAttributeNode setUseBytesAttrNode = SetFixedAttributeNode.create("useBytes"); @@ -699,7 +746,7 @@ public class GrepFunctions { @Child PCRERFFI.GetCaptureCountNode getCaptureCountNode = RFFIFactory.getRFFI().getPCRERFFI().createGetCaptureCountNode(); static { - Casts casts = new Casts(Regexp.class); + Casts casts = new Casts(Regexpr.class); castPattern(casts); castText(casts, "text"); castIgnoreCase(casts); @@ -735,11 +782,9 @@ public class GrepFunctions { @Specialization @TruffleBoundary - protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, byte ignoreCaseL, byte perlL, byte fixedL, byte useBytesL) { - checkExtraArgs(RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, useBytesL, RRuntime.LOGICAL_FALSE); - boolean ignoreCase = RRuntime.fromLogical(ignoreCaseL); - boolean fixed = RRuntime.fromLogical(fixedL); - boolean perl = RRuntime.fromLogical(perlL); + protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, boolean ignoreCase, boolean perl, boolean fixed, boolean useBytesL, + @Cached("createCommon()") CommonCodeNode common) { + common.checkExtraArgs(false, false, false, useBytesL, false); if (patternArg.getLength() > 1) { throw RInternalError.unimplemented("multi-element patterns in regexpr not implemented yet"); } @@ -761,7 +806,7 @@ public class GrepFunctions { Arrays.fill(result, 1); } else { for (int i = 0; i < vector.getLength(); i++) { - Info res = getInfo(pattern, vector.getDataAt(i), ignoreCase, perl, fixed).get(0); + Info res = getInfo(common, pattern, vector.getDataAt(i), ignoreCase, perl, fixed).get(0); result[i] = res.index; matchLength[i] = res.size; if (res.hasCapture) { @@ -806,7 +851,7 @@ public class GrepFunctions { return ret; } - protected List<Info> getInfo(String pattern, String text, boolean ignoreCase, boolean perl, boolean fixed) { + protected List<Info> getInfo(CommonCodeNode common, String pattern, String text, boolean ignoreCase, boolean perl, boolean fixed) { List<Info> list = new ArrayList<>(); if (fixed) { int index = 0; @@ -823,7 +868,7 @@ public class GrepFunctions { index += pattern.length(); } } else if (perl) { - PCRERFFI.Result pcre = compilePerlPattern(pattern, ignoreCase); + PCRERFFI.Result pcre = common.compilePerlPattern(pattern, ignoreCase); int maxCaptureCount = getCaptureCountNode.execute(pcre.result, 0); int[] ovector = new int[(maxCaptureCount + 1) * 3]; int offset = 0; @@ -876,8 +921,116 @@ public class GrepFunctions { } } + @ImportStatic(GrepFunctions.class) + @RBuiltin(name = "regexec", kind = INTERNAL, parameterNames = {"pattern", "text", "ignore.case", "fixed", "useBytes"}, behavior = PURE) + public abstract static class Regexec extends RBuiltinNode.Arg5 { + + @Child SetFixedAttributeNode setMatchLengthAttrNode = SetFixedAttributeNode.create("match.length"); + @Child SetFixedAttributeNode setUseBytesAttrNode = SetFixedAttributeNode.create("useBytes"); + @Child SetFixedAttributeNode setDimNamesAttrNode = SetFixedAttributeNode.createDimNames(); + + static { + Casts casts = new Casts(Regexec.class); + castPattern(casts); + castText(casts, "text"); + castIgnoreCase(casts); + castFixed(casts, RRuntime.LOGICAL_FALSE); + castUseBytes(casts); + } + + protected static final class Info { + protected final int index; + protected final int size; + protected final int[] captureStart; + protected final int[] captureLength; + protected final String[] captureNames; + protected final boolean hasCapture; + + public Info(int index, int size, int[] captureStart, int[] captureLength, String[] captureNames) { + this.index = index; + this.size = size; + this.captureStart = captureStart; + this.captureLength = captureLength; + this.captureNames = captureNames; + this.hasCapture = captureStart != null && captureLength != null; + } + } + + @Specialization + @TruffleBoundary + protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, boolean ignoreCase, boolean fixed, boolean useBytes, + @Cached("createCommon()") CommonCodeNode common) { + common.checkExtraArgs(false, false, false, useBytes, false); + if (patternArg.getLength() > 1) { + throw RInternalError.unimplemented("multi-element patterns in regexpr not implemented yet"); + } + RList ret = RDataFactory.createList(vector.getLength()); + String pattern = patternArg.getDataAt(0); + pattern = RegExp.checkPreDefinedClasses(pattern); + // TODO: useBytes normally depends on the value of the parameter and (if false) on + // whether the string is ASCII + for (int i = 0; i < vector.getLength(); i++) { + int[] matchPos; + int[] matchLength; + if (pattern.length() == 0) { + // emtpy pattern + matchPos = new int[]{1}; + matchLength = new int[]{0}; + } else { + List<Info> res = getInfo(pattern, vector.getDataAt(i), ignoreCase, fixed); + matchPos = new int[res.size()]; + matchLength = new int[res.size()]; + for (int j = 0; j < res.size(); j++) { + matchPos[j] = res.get(j).index; + matchLength[j] = res.get(j).size; + } + } + RIntVector matches = RDataFactory.createIntVector(matchPos, RDataFactory.COMPLETE_VECTOR); + setMatchLengthAttrNode.execute(matches, RDataFactory.createIntVector(matchLength, RDataFactory.COMPLETE_VECTOR)); + ret.setElement(i, matches); + } + if (useBytes) { + setUseBytesAttrNode.execute(ret, RRuntime.LOGICAL_TRUE); + } + return ret; + } + + protected List<Info> getInfo(String pattern, String text, boolean ignoreCase, boolean fixed) { + List<Info> list = new ArrayList<>(); + if (fixed) { + int index; + if (ignoreCase) { + index = text.toLowerCase().indexOf(pattern.toLowerCase()); + } else { + index = text.indexOf(pattern); + } + if (index != -1) { + list.add(new Info(index + 1, pattern.length(), null, null, null)); + } + } else { + Matcher m = getPatternMatcher(pattern, text, ignoreCase); + if (m.find()) { + for (int i = 0; i <= m.groupCount(); i++) { + list.add(new Info(m.start(i) + 1, m.end(i) - m.start(i), null, null, null)); + } + } + } + if (list.size() > 0) { + return list; + } + list.add(new Info(-1, -1, null, null, null)); + return list; + } + + @TruffleBoundary + private static Matcher getPatternMatcher(String pattern, String text, boolean ignoreCase) { + return Pattern.compile(pattern, ignoreCase ? Pattern.CASE_INSENSITIVE : 0).matcher(text); + } + } + + @ImportStatic(GrepFunctions.class) @RBuiltin(name = "gregexpr", kind = INTERNAL, parameterNames = {"pattern", "text", "ignore.case", "perl", "fixed", "useBytes"}, behavior = PURE) - public abstract static class Gregexpr extends Regexp { + public abstract static class Gregexpr extends Regexpr { @Child SetFixedAttributeNode setMatchLengthAttrNode = SetFixedAttributeNode.create("match.length"); @Child SetFixedAttributeNode setUseBytesAttrNode = SetFixedAttributeNode.create("useBytes"); @@ -914,11 +1067,12 @@ public class GrepFunctions { @Specialization @TruffleBoundary @Override - protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, byte ignoreCaseL, byte perlL, byte fixedL, byte useBytesL) { - checkExtraArgs(RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, useBytesL, RRuntime.LOGICAL_FALSE); - boolean ignoreCase = RRuntime.fromLogical(ignoreCaseL); - boolean fixed = RRuntime.fromLogical(fixedL); - boolean perl = RRuntime.fromLogical(perlL); + protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, boolean ignoreCaseL, boolean perlL, boolean fixedL, boolean useBytesL, + @Cached("createCommon()") CommonCodeNode common) { + common.checkExtraArgs(false, false, false, useBytesL, false); + boolean ignoreCase = ignoreCaseL; + boolean fixed = fixedL; + boolean perl = perlL; if (patternArg.getLength() > 1) { throw RInternalError.unimplemented("multi-element patterns in gregexpr not implemented yet"); } @@ -945,7 +1099,7 @@ public class GrepFunctions { setUseBytesAttrNode.execute(res, RRuntime.LOGICAL_TRUE); } } else { - List<Info> l = getInfo(pattern, vector.getDataAt(i), ignoreCase, perl, fixed); + List<Info> l = getInfo(common, pattern, vector.getDataAt(i), ignoreCase, perl, fixed); res = toIndexOrSizeVector(l, true); setMatchLengthAttrNode.execute(res, toIndexOrSizeVector(l, false)); if (useBytes) { @@ -1022,12 +1176,13 @@ public class GrepFunctions { } } + @ImportStatic(GrepFunctions.class) @RBuiltin(name = "agrep", kind = INTERNAL, parameterNames = {"pattern", "x", "ignore.case", "value", "costs", "bounds", "useBytes", "fixed"}, behavior = PURE) - public abstract static class AGrep extends CommonCodeAdapter { + public abstract static class AGrep extends RBuiltinNode.Arg8 { static { Casts casts = new Casts(AGrep.class); - castPattern(casts); + castPatternSingle(casts); castText(casts, "x"); castIgnoreCase(casts); castValue(casts); @@ -1040,15 +1195,14 @@ public class GrepFunctions { @SuppressWarnings("unused") @Specialization @TruffleBoundary - protected Object aGrep(RAbstractStringVector patternArg, RAbstractStringVector vector, byte ignoreCase, byte value, RAbstractIntVector costs, RAbstractDoubleVector bounds, byte useBytes, - byte fixed) { + protected Object aGrep(String pattern, RAbstractStringVector vector, boolean ignoreCase, boolean value, RAbstractIntVector costs, RAbstractDoubleVector bounds, boolean useBytes, boolean fixed, + @Cached("createCommon()") CommonCodeNode common) { // TODO implement completely; this is a very basic implementation for fixed=TRUE only. - checkExtraArgs(ignoreCase, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, useBytes, RRuntime.LOGICAL_FALSE); - valueCheck(value); - checkNotImplemented(!RRuntime.fromLogical(fixed), "fixed", false); + common.checkExtraArgs(ignoreCase, false, false, useBytes, false); + common.valueCheck(value); + common.checkNotImplemented(!fixed, "fixed", false); int[] tmp = new int[vector.getLength()]; int numMatches = 0; - String pattern = patternArg.getDataAt(0); long maxDistance = Math.round(pattern.length() * bounds.getDataAt(0)); for (int i = 0; i < vector.getLength(); i++) { int ld = ld(pattern, vector.getDataAt(i)); @@ -1057,7 +1211,7 @@ public class GrepFunctions { numMatches++; } } - tmp = trimIntResult(tmp, numMatches, tmp.length); + tmp = common.trimIntResult(tmp, numMatches, tmp.length); if (tmp == null) { return RDataFactory.createEmptyIntVector(); } else { @@ -1138,12 +1292,13 @@ public class GrepFunctions { } } + @ImportStatic(GrepFunctions.class) @RBuiltin(name = "agrepl", kind = INTERNAL, parameterNames = {"pattern", "x", "ignore.case", "value", "costs", "bounds", "useBytes", "fixed"}, behavior = PURE) - public abstract static class AGrepL extends CommonCodeAdapter { + public abstract static class AGrepL extends RBuiltinNode.Arg8 { static { Casts casts = new Casts(AGrepL.class); - castPattern(casts); + castPatternSingle(casts); castText(casts, "x"); castIgnoreCase(casts); castValue(casts); @@ -1156,12 +1311,11 @@ public class GrepFunctions { @SuppressWarnings("unused") @Specialization @TruffleBoundary - protected Object aGrep(RAbstractStringVector patternArg, RAbstractStringVector vector, byte ignoreCase, byte value, RAbstractIntVector costs, RAbstractDoubleVector bounds, byte useBytes, - byte fixed) { + protected Object aGrep(String pattern, RAbstractStringVector vector, boolean ignoreCase, boolean value, RAbstractIntVector costs, RAbstractDoubleVector bounds, boolean useBytes, boolean fixed, + @Cached("createCommon()") CommonCodeNode common) { // TODO implement properly, this only supports strict equality! - checkExtraArgs(ignoreCase, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, useBytes, RRuntime.LOGICAL_FALSE); + common.checkExtraArgs(ignoreCase, false, false, useBytes, false); byte[] data = new byte[vector.getLength()]; - String pattern = patternArg.getDataAt(0); for (int i = 0; i < vector.getLength(); i++) { data[i] = RRuntime.asLogical(pattern.equals(vector.getDataAt(i))); } @@ -1169,14 +1323,15 @@ public class GrepFunctions { } } + @ImportStatic(GrepFunctions.class) @RBuiltin(name = "strsplit", kind = INTERNAL, parameterNames = {"x", "split", "fixed", "perl", "useBytes"}, behavior = PURE) - public abstract static class Strsplit extends CommonCodeAdapter { + public abstract static class Strsplit extends RBuiltinNode.Arg5 { @Child PCRERFFI.ExecNode execNode = RFFIFactory.getRFFI().getPCRERFFI().createExecNode(); static { Casts casts = new Casts(Strsplit.class); - casts.arg("x").mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.NON_CHARACTER); - casts.arg("split").mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.NON_CHARACTER); + casts.arg("x").mustBe(stringValue(), RError.Message.NON_CHARACTER); + casts.arg("split").mustBe(stringValue(), RError.Message.NON_CHARACTER); castFixed(casts, RRuntime.LOGICAL_FALSE); castPerl(casts); castUseBytes(casts); @@ -1186,14 +1341,14 @@ public class GrepFunctions { @Specialization @TruffleBoundary - protected RList split(RAbstractStringVector x, RAbstractStringVector splitArg, byte fixedLogical, byte perlLogical, @SuppressWarnings("unused") byte useBytes) { - boolean fixed = RRuntime.fromLogical(fixedLogical); - boolean perl = checkPerlFixed(RRuntime.fromLogical(perlLogical), fixed); + protected RList split(RAbstractStringVector x, RAbstractStringVector splitArg, boolean fixed, boolean perlLogical, @SuppressWarnings("unused") boolean useBytes, + @Cached("createCommon()") CommonCodeNode common) { + boolean perl = common.checkPerlFixed(perlLogical, fixed); RStringVector[] result = new RStringVector[x.getLength()]; // treat split = NULL as split = "" RAbstractStringVector split = splitArg.getLength() == 0 ? RDataFactory.createStringVectorFromScalar("") : splitArg; String[] splits = new String[split.getLength()]; - long pcreTables = perl ? maketablesNode.execute() : 0; + long pcreTables = perl ? common.maketablesNode.execute() : 0; PCRERFFI.Result[] pcreSplits = perl ? new PCRERFFI.Result[splits.length] : null; na.enable(x); @@ -1202,10 +1357,10 @@ public class GrepFunctions { splits[i] = fixed || perl ? split.getDataAt(i) : RegExp.checkPreDefinedClasses(split.getDataAt(i)); if (perl) { if (!currentSplit.isEmpty()) { - pcreSplits[i] = compileNode.execute(currentSplit, 0, pcreTables); + pcreSplits[i] = common.compileNode.execute(currentSplit, 0, pcreTables); if (pcreSplits[i].result == 0) { // TODO output warning if pcre.errorMessage not NULL - throw RError.error(this, RError.Message.INVALID_REGEXP, currentSplit); + throw error(RError.Message.INVALID_REGEXP, currentSplit); } // TODO pcre_study for vectors > 10 ? (cf GnuR) } @@ -1252,9 +1407,9 @@ public class GrepFunctions { @Fallback protected RList split(Object x, Object splitArg, Object fixedLogical, Object perlLogical, Object useBytes) { if (!(x instanceof RAbstractStringVector)) { - throw RError.error(this, RError.Message.NON_CHARACTER); + throw error(RError.Message.NON_CHARACTER); } else { - throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); + throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java index 6d4a9370e312e67de7d2ab785a536ca5b552db71..965159a003e27909512544a134e49257fdb42e48 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java @@ -79,7 +79,7 @@ public class HiddenInternalFunctions { * Transcribed from GnuR {@code do_makeLazy} in src/main/builtin.c. */ @RBuiltin(name = "makeLazy", visibility = OFF, kind = INTERNAL, parameterNames = {"names", "values", "expr", "eval.env", "assign.env"}, behavior = COMPLEX) - public abstract static class MakeLazy extends RBuiltinNode { + public abstract static class MakeLazy extends RBuiltinNode.Arg5 { @Child private Eval eval; private void initEval() { @@ -127,7 +127,7 @@ public class HiddenInternalFunctions { * not an error, but is used as an override mechanism. */ if (!RContext.getInstance().getLoadingBase()) { - throw RError.error(this, ex); + throw error(ex); } } } @@ -142,7 +142,7 @@ public class HiddenInternalFunctions { * possibly with different names. Promises are not forced and active bindings are preserved. */ @RBuiltin(name = "importIntoEnv", kind = INTERNAL, parameterNames = {"impenv", "impnames", "expenv", "expnames"}, behavior = COMPLEX) - public abstract static class ImportIntoEnv extends RBuiltinNode { + public abstract static class ImportIntoEnv extends RBuiltinNode.Arg4 { static { Casts casts = new Casts(ImportIntoEnv.class); @@ -157,7 +157,7 @@ public class HiddenInternalFunctions { protected RNull importIntoEnv(REnvironment impEnv, RAbstractStringVector impNames, REnvironment expEnv, RAbstractStringVector expNames) { int length = impNames.getLength(); if (length != expNames.getLength()) { - throw RError.error(this, Message.IMP_EXP_NAMES_MATCH); + throw error(Message.IMP_EXP_NAMES_MATCH); } for (int i = 0; i < length; i++) { String impsym = impNames.getDataAt(i); @@ -173,7 +173,7 @@ public class HiddenInternalFunctions { try { impEnv.put(impsym, binding); } catch (PutException ex) { - throw RError.error(RError.SHOW_CALLER, ex); + throw error(ex); } } return RNull.instance; @@ -184,7 +184,7 @@ public class HiddenInternalFunctions { * Transcribed from {@code lazyLoaadDBFetch} in src/serialize.c. */ @RBuiltin(name = "lazyLoadDBfetch", kind = PRIMITIVE, parameterNames = {"key", "datafile", "compressed", "envhook"}, behavior = PURE) - public abstract static class LazyLoadDBFetch extends RBuiltinNode { + public abstract static class LazyLoadDBFetch extends RBuiltinNode.Arg4 { @Child private CallRFunctionCachedNode callCache = CallRFunctionCachedNodeGen.create(2); @@ -233,7 +233,7 @@ public class HiddenInternalFunctions { if (compression == 2 || compression == 3) { RCompression.Type type = RCompression.Type.fromTypeChar(dbData[4]); if (type == null) { - RError.warning(this, RError.Message.GENERIC, "unknown compression type"); + warning(RError.Message.GENERIC, "unknown compression type"); return RNull.instance; } byte[] data = new byte[length - 5]; @@ -247,7 +247,7 @@ public class HiddenInternalFunctions { } } if (!rc) { - throw RError.error(this, RError.Message.LAZY_LOAD_DB_CORRUPT, dbPath); + throw error(RError.Message.LAZY_LOAD_DB_CORRUPT, dbPath); } try { RSerialize.CallHook callHook = new RSerialize.CallHook() { @@ -274,7 +274,7 @@ public class HiddenInternalFunctions { } @RBuiltin(name = "getRegisteredRoutines", kind = INTERNAL, parameterNames = "info", behavior = COMPLEX) - public abstract static class GetRegisteredRoutines extends RBuiltinNode { + public abstract static class GetRegisteredRoutines extends RBuiltinNode.Arg1 { private static final RStringVector NAMES = RDataFactory.createStringVector(new String[]{".C", ".Call", ".Fortran", ".External"}, RDataFactory.COMPLETE_VECTOR); private static final RStringVector NATIVE_ROUTINE_LIST = RDataFactory.createStringVectorFromScalar("NativeRoutineList"); @@ -284,7 +284,7 @@ public class HiddenInternalFunctions { @Specialization protected RList getRegisteredRoutines(@SuppressWarnings("unused") RNull info) { - throw RError.error(this, RError.Message.NULL_DLLINFO); + throw error(RError.Message.NULL_DLLINFO); } @Specialization(guards = "isDLLInfo(externalPtr)") @@ -315,7 +315,7 @@ public class HiddenInternalFunctions { @Fallback protected RList getRegisteredRoutines(@SuppressWarnings("unused") Object info) { - throw RError.error(this, RError.Message.REQUIRES_DLLINFO); + throw error(RError.Message.REQUIRES_DLLINFO); } protected static boolean isDLLInfo(RExternalPtr externalPtr) { @@ -324,7 +324,7 @@ public class HiddenInternalFunctions { } @RBuiltin(name = "getVarsFromFrame", kind = INTERNAL, parameterNames = {"vars", "e", "force"}, behavior = COMPLEX) - public abstract static class GetVarsFromFrame extends RBuiltinNode { + public abstract static class GetVarsFromFrame extends RBuiltinNode.Arg3 { @Child private PromiseHelperNode promiseHelper; static { @@ -339,7 +339,7 @@ public class HiddenInternalFunctions { String var = varsVec.getDataAt(i); Object value = env.get(var); if (value == null) { - throw RError.error(this, RError.Message.UNKNOWN_OBJECT, var); + throw error(RError.Message.UNKNOWN_OBJECT, var); } if (force && value instanceof RPromise) { if (promiseHelper == null) { @@ -356,12 +356,12 @@ public class HiddenInternalFunctions { @SuppressWarnings("unused") @Fallback protected RList getVarsFromFrame(Object varsVec, Object env, Object forceArg) { - throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); + throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); } } @RBuiltin(name = "lazyLoadDBinsertValue", kind = INTERNAL, parameterNames = {"value", "file", "ascii", "compsxp", "hook"}, behavior = COMPLEX) - public abstract static class LazyLoadDBinsertValue extends RBuiltinNode { + public abstract static class LazyLoadDBinsertValue extends RBuiltinNode.Arg5 { @Child private CallRFunctionCachedNode callCache = CallRFunctionCachedNodeGen.create(2); @@ -379,7 +379,7 @@ public class HiddenInternalFunctions { @TruffleBoundary private RIntVector lazyLoadDBinsertValueInternal(MaterializedFrame frame, Object value, RAbstractStringVector file, int type, int compression, RFunction hook) { if (!(compression == 1 || compression == 3)) { - throw RError.error(this, Message.GENERIC, "unsupported compression"); + throw error(Message.GENERIC, "unsupported compression"); } RSerialize.CallHook callHook = new RSerialize.CallHook() { @@ -403,7 +403,7 @@ public class HiddenInternalFunctions { cdata = new byte[outLen]; boolean rc = RCompression.compress(ctype, data, cdata); if (!rc) { - throw RError.error(this, Message.GENERIC, "zlib compress error"); + throw error(Message.GENERIC, "zlib compress error"); } } else if (compression == 3) { ctype = RCompression.Type.XZ; @@ -412,7 +412,7 @@ public class HiddenInternalFunctions { cdata = new byte[outLen]; boolean rc = RCompression.compress(ctype, data, cdata); if (!rc) { - throw RError.error(this, Message.GENERIC, "lzma compress error"); + throw error(Message.GENERIC, "lzma compress error"); } } else { throw RInternalError.shouldNotReachHere(); @@ -424,14 +424,14 @@ public class HiddenInternalFunctions { } catch (Throwable ex) { // Exceptions have been observed that were masked and very hard to find ex.printStackTrace(); - throw RInternalError.shouldNotReachHere("lazyLoadDBinsertValue exception"); + throw RInternalError.shouldNotReachHere(ex, "lazyLoadDBinsertValue exception"); } } @SuppressWarnings("unused") @Fallback protected Object lazyLoadDBinsertValue(Object value, Object file, Object ascii, Object compsxp, Object hook) { - throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); + throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); } /** @@ -465,7 +465,7 @@ public class HiddenInternalFunctions { } @RBuiltin(name = "lazyLoadDBflush", kind = INTERNAL, parameterNames = "path", behavior = COMPLEX) - public abstract static class LazyLoadDBFlush extends RBuiltinNode { + public abstract static class LazyLoadDBFlush extends RBuiltinNode.Arg1 { static { Casts.noCasts(LazyLoadDBFlush.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java index 62b894730ecde4abf897289b4e4561d5e0e1be86..4b75dccff92fd1ddda1fb5943fb4c8361eb1ad68 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java @@ -37,15 +37,15 @@ import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "iconv", kind = INTERNAL, parameterNames = {"x", "from", "to", "sub", "mark", "toRaw"}, behavior = PURE) -public abstract class IConv extends RBuiltinNode { +public abstract class IConv extends RBuiltinNode.Arg6 { static { Casts casts = new Casts(IConv.class); - casts.arg("x").mustBe(stringValue(), RError.NO_CALLER, RError.Message.NOT_CHARACTER_VECTOR, "x"); + casts.arg("x").mustBe(stringValue(), RError.Message.NOT_CHARACTER_VECTOR, "x"); // with default error message, NO_CALLER does not work - casts.arg("from").defaultError(RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "from").mustBe(stringValue()).asStringVector().mustBe(size(1)); - casts.arg("to").defaultError(RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "to").mustBe(stringValue()).asStringVector().mustBe(size(1)); - casts.arg("sub").defaultError(RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "sub").mustBe(stringValue()).asStringVector().mustBe(size(1)); + casts.arg("from").defaultError(RError.Message.INVALID_ARGUMENT, "from").mustBe(stringValue()).asStringVector().mustBe(size(1)); + casts.arg("to").defaultError(RError.Message.INVALID_ARGUMENT, "to").mustBe(stringValue()).asStringVector().mustBe(size(1)); + casts.arg("sub").defaultError(RError.Message.INVALID_ARGUMENT, "sub").mustBe(stringValue()).asStringVector().mustBe(size(1)); casts.arg("mark").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); casts.arg("toRaw").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java index 3f5769de6059e2d3da274be8e43051401d5a7aa1..9200d000ff439387eddd20b366953f7acfae0a2c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java @@ -49,8 +49,6 @@ import com.oracle.truffle.r.runtime.data.RListBase; import com.oracle.truffle.r.runtime.data.RPairList; import com.oracle.truffle.r.runtime.data.RS4Object; import com.oracle.truffle.r.runtime.data.RSymbol; -import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.IdenticalVisitor; @@ -67,7 +65,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; * checked for NA (regardless of whether they are used). */ @RBuiltin(name = "identical", kind = INTERNAL, parameterNames = {"x", "y", "num.eq", "single.NA", "attrib.as.set", "ignore.bytecode", "ignore.environment"}, behavior = PURE) -public abstract class Identical extends RBuiltinNode { +public abstract class Identical extends RBuiltinNode.Arg7 { protected abstract byte executeByte(Object x, Object y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment); @@ -183,18 +181,6 @@ public abstract class Identical extends RBuiltinNode { return RRuntime.LOGICAL_FALSE; } - @SuppressWarnings("unused") - @Specialization - protected byte doInternalIdentical(RAbstractLogicalVector x, REnvironment y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) { - return RRuntime.LOGICAL_FALSE; - } - - @SuppressWarnings("unused") - @Specialization - protected byte doInternalIdentical(REnvironment x, RAbstractLogicalVector y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) { - return RRuntime.LOGICAL_FALSE; - } - @SuppressWarnings("unused") @Specialization protected byte doInternalIdentical(REnvironment x, REnvironment y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) { @@ -288,24 +274,6 @@ public abstract class Identical extends RBuiltinNode { return identicalAttr(x, y, numEq, singleNA, attribAsSet, ignoreBytecode, ignoreEnvironment); } - @SuppressWarnings("unused") - @Specialization - protected byte doInternalIdenticalGeneric(RFunction x, RAbstractContainer y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) { - return RRuntime.LOGICAL_FALSE; - } - - @SuppressWarnings("unused") - @Specialization - protected byte doInternalIdenticalGeneric(RLanguage x, RAbstractContainer y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) { - return RRuntime.LOGICAL_FALSE; - } - - @SuppressWarnings("unused") - @Specialization - protected byte doInternalIdenticalGeneric(RAbstractContainer x, RFunction y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) { - return RRuntime.LOGICAL_FALSE; - } - @Specialization protected byte doInternalIdenticalGeneric(RS4Object x, RS4Object y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) { if (x.isS4() != y.isS4()) { @@ -368,11 +336,8 @@ public abstract class Identical extends RBuiltinNode { @SuppressWarnings("unused") @Fallback protected byte doInternalIdenticalWrongTypes(Object x, Object y, Object numEq, Object singleNA, Object attribAsSet, Object ignoreBytecode, Object ignoreEnvironment) { - if (x.getClass() != y.getClass()) { - return RRuntime.LOGICAL_FALSE; - } else { - throw RInternalError.unimplemented(); - } + assert x.getClass() != y.getClass(); + return RRuntime.LOGICAL_FALSE; } protected boolean vectorsLists(RAbstractVector x, RAbstractVector y) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InheritsBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InheritsBuiltin.java index b45abeda284522f6bda8d51103d0b086b674529f..bcd8c7f39fa30c4104f05c8bcd3b316d157e8be7 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InheritsBuiltin.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InheritsBuiltin.java @@ -27,7 +27,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "inherits", kind = INTERNAL, parameterNames = {"x", "what", "which"}, behavior = PURE) -public abstract class InheritsBuiltin extends RBuiltinNode { +public abstract class InheritsBuiltin extends RBuiltinNode.Arg3 { @Child InheritsNode inheritsNode = InheritsNodeGen.create(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java index 0b85315703321a178abb85d2a20782ad5fb1d173..c595f2f99755209a0dd058d93023e12b10e665c8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java @@ -34,11 +34,11 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; @RBuiltin(name = "intToBits", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) -public abstract class IntToBits extends RBuiltinNode { +public abstract class IntToBits extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(IntToBits.class); - casts.arg("x").asIntegerVector(); + casts.arg("x").mustNotBeMissing().asIntegerVector(); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java index 51a84c924e9abfcbc60145876e037daae5afa825..531147ade95d62163384d83c1b5c79f337ee2418 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java @@ -30,7 +30,6 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -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.builtins.RBuiltin; @@ -41,11 +40,11 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "intToUtf8", kind = INTERNAL, parameterNames = {"x", "multiple"}, behavior = PURE) -public abstract class IntToUtf8 extends RBuiltinNode { +public abstract class IntToUtf8 extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(IntToUtf8.class); - casts.arg("x").asIntegerVector(); + casts.arg("x").mustNotBeMissing().asIntegerVector(); casts.arg("multiple").mustNotBeNull().asLogicalVector().findFirst().map(toBoolean()); } @@ -71,7 +70,7 @@ public abstract class IntToUtf8 extends RBuiltinNode { try { result[j] = new String(new int[]{temp}, 0, 1); } catch (IllegalArgumentException e) { - throw RError.error(RError.SHOW_CALLER, Message.GENERIC, "illegal unicode code point"); + throw error(Message.GENERIC, "illegal unicode code point"); } } } @@ -97,7 +96,7 @@ public abstract class IntToUtf8 extends RBuiltinNode { try { return new String(result, 0, pos); } catch (IllegalArgumentException e) { - throw RError.error(RError.SHOW_CALLER, Message.GENERIC, "illegal unicode code point"); + throw error(Message.GENERIC, "illegal unicode code point"); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.java index 55bf8f6b8c1b8d87a22533e736818476d4c1a7e1..ef734b838ba875c3bec6bb12c9b8be9ba28554fb 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.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 @@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.context.RContext; @RBuiltin(name = "interactive", kind = PRIMITIVE, parameterNames = {}, behavior = READS_STATE) -public abstract class Interactive extends RBuiltinNode { +public abstract class Interactive extends RBuiltinNode.Arg0 { @Specialization protected byte interactive() { return RRuntime.asLogical(RContext.getInstance().isInteractive()); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.java index 4a50c81280e7b7eed1a0050dcecf1a5a3eb06acb..e355db172763768bbe7828ea0f4ee066d4f88e73 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.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 @@ -36,7 +36,11 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; * visible. */ @RBuiltin(name = ".Internal", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"call"}, nonEvalArgs = 0, behavior = COMPLEX) -public abstract class Internal extends RBuiltinNode { +public abstract class Internal extends RBuiltinNode.Arg1 { + + static { + Casts.noCasts(Internal.class); + } @Specialization protected Object doInternal(@SuppressWarnings("unused") Object x) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Invisible.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Invisible.java index 55ec16e7d4e238195b4c80da059c9f524a5b9525..de675420cf23efa59e1529b5e7430101f841b3bb 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Invisible.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Invisible.java @@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RNull; @RBuiltin(name = "invisible", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x"}, behavior = COMPLEX) -public abstract class Invisible extends RBuiltinNode { +public abstract class Invisible extends RBuiltinNode.Arg1 { static { Casts.noCasts(Invisible.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsATTY.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsATTY.java index 32fe9994366140e09659f5fd7309885739dc5d9b..8599ff3cdf59235b5e1d89728dcf16114debbcfd 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsATTY.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsATTY.java @@ -29,6 +29,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.conn.RConnection; @@ -38,7 +39,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @RBuiltin(name = "isatty", kind = INTERNAL, parameterNames = {"con"}, behavior = PURE) -public abstract class IsATTY extends RBuiltinNode { +public abstract class IsATTY extends RBuiltinNode.Arg1 { static { Casts.noCasts(IsATTY.class); @@ -48,7 +49,7 @@ public abstract class IsATTY extends RBuiltinNode { @TruffleBoundary protected byte isATTYNonConnection(RAbstractIntVector con) { if (con.getLength() == 1) { - RStringVector clazz = con.getClassHierarchy(); + RStringVector clazz = ClassHierarchyNode.getClassHierarchy(con); for (int i = 0; i < clazz.getLength(); i++) { if ("connection".equals(clazz.getDataAt(i))) { RConnection connection = RContext.getInstance().stateRConnection.getConnection(con.getDataAt(0), false); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java index f1ce895c28b731c223a6d7aff58f444a03e86ec9..075d0dbb0345c8a8fbb981fac42b4732aa436adb 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java @@ -29,12 +29,13 @@ import java.util.Arrays; import java.util.function.DoublePredicate; import java.util.function.IntPredicate; -import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode; +import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.unary.TypeofNode; -import com.oracle.truffle.r.nodes.unary.TypeofNodeGen; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -52,7 +53,11 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; public class IsFiniteFunctions { - public abstract static class Adapter extends RBuiltinNode { + public abstract static class Adapter extends RBuiltinNode.Arg1 { + + @Child private GetDimAttributeNode getDims = GetDimAttributeNode.create(); + @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create(); + @FunctionalInterface protected interface ComplexPredicate { boolean test(RComplex x); @@ -78,22 +83,16 @@ public class IsFiniteFunctions { return doFunConstant(x, RRuntime.LOGICAL_FALSE); } - @Child private TypeofNode typeofNode; - @Fallback + @TruffleBoundary protected Object doIsFiniteOther(Object x) { - if (typeofNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - typeofNode = insert(TypeofNodeGen.create()); - } - String type = typeofNode.execute(x).getName(); - throw RError.error(this, RError.Message.DEFAULT_METHOD_NOT_IMPLEMENTED_FOR_TYPE, type); + throw error(RError.Message.DEFAULT_METHOD_NOT_IMPLEMENTED_FOR_TYPE, TypeofNode.getTypeof(x).getName()); } protected RLogicalVector doFunConstant(RAbstractVector x, byte value) { byte[] b = new byte[x.getLength()]; Arrays.fill(b, value); - return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR); + return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x)); } protected RLogicalVector doFunDouble(RAbstractDoubleVector x, DoublePredicate fun) { @@ -101,7 +100,7 @@ public class IsFiniteFunctions { for (int i = 0; i < b.length; i++) { b[i] = RRuntime.asLogical(fun.test(x.getDataAt(i))); } - return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR); + return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x)); } protected RLogicalVector doFunLogical(RAbstractLogicalVector x, LogicalPredicate fun) { @@ -109,7 +108,7 @@ public class IsFiniteFunctions { for (int i = 0; i < b.length; i++) { b[i] = RRuntime.asLogical(fun.test(x.getDataAt(i))); } - return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR); + return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x)); } protected RLogicalVector doFunInt(RAbstractIntVector x, IntPredicate fun) { @@ -117,7 +116,7 @@ public class IsFiniteFunctions { for (int i = 0; i < b.length; i++) { b[i] = RRuntime.asLogical(fun.test(x.getDataAt(i))); } - return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR); + return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x)); } protected RLogicalVector doFunComplex(RAbstractComplexVector x, ComplexPredicate fun) { @@ -125,7 +124,7 @@ public class IsFiniteFunctions { for (int i = 0; i < b.length; i++) { b[i] = RRuntime.asLogical(fun.test(x.getDataAt(i))); } - return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR); + return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x)); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsListFactor.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsListFactor.java index 48cc21c9563ce13f760332e53ca650e2e6a15229..dd4dab9a055702a74f81034f690083ba3f4096d6 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsListFactor.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsListFactor.java @@ -29,7 +29,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; // from apply.c @RBuiltin(name = "islistfactor", kind = INTERNAL, parameterNames = {"x", "recursive"}, behavior = PURE) -public abstract class IsListFactor extends RBuiltinNode { +public abstract class IsListFactor extends RBuiltinNode.Arg2 { protected abstract static class IsListFactorInternal extends Node { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsMethodsDispatchOn.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsMethodsDispatchOn.java index 22f316102e814c4c4fc05860d39973dc5e37faec..0318822491f553b8d30a16681e9a13fc31d114af 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsMethodsDispatchOn.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsMethodsDispatchOn.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 @@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.context.RContext; @RBuiltin(name = ".isMethodsDispatchOn", kind = PRIMITIVE, parameterNames = {}, behavior = READS_STATE) -public abstract class IsMethodsDispatchOn extends RBuiltinNode { +public abstract class IsMethodsDispatchOn extends RBuiltinNode.Arg0 { public abstract byte execute(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java index 39826ee9a75c775a6871bc9507ca43461c737a52..c08de1b1f10abdba38904bb6e90c461d64b64727 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java @@ -54,7 +54,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "is.na", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE) -public abstract class IsNA extends RBuiltinNode { +public abstract class IsNA extends RBuiltinNode.Arg1 { @Child private IsNA recursiveIsNA; @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create(); @@ -191,7 +191,7 @@ public abstract class IsNA extends RBuiltinNode { @Specialization protected RLogicalVector isNA(RNull value) { - RError.warning(this, RError.Message.IS_NA_TO_NON_VECTOR, value.getRType().getName()); + warning(RError.Message.IS_NA_TO_NON_VECTOR, value.getRType().getName()); return RDataFactory.createEmptyLogicalVector(); } @@ -199,7 +199,7 @@ public abstract class IsNA extends RBuiltinNode { // fallback @Fallback protected byte isNA(Object value) { - RError.warning(this, RError.Message.IS_NA_TO_NON_VECTOR, ((RTypedValue) value).getRType().getName()); + warning(RError.Message.IS_NA_TO_NON_VECTOR, ((RTypedValue) value).getRType().getName()); return RRuntime.LOGICAL_FALSE; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsS4.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsS4.java index d4939ab3a5e1d9e3e3688d6edfa20ed44bac55c5..231e1e43fe69f01ebc7698576731ebbfc4f4e396 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsS4.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsS4.java @@ -34,7 +34,7 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RTypedValue; @RBuiltin(name = "isS4", kind = PRIMITIVE, parameterNames = {"object"}, behavior = PURE) -public abstract class IsS4 extends RBuiltinNode { +public abstract class IsS4 extends RBuiltinNode.Arg1 { static { Casts.noCasts(IsS4.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java index b9d87fff252c7bacefbbd5f4d62d4bb676fcc283..9152317546763b55b0cce7c33366cf254e19dfe0 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java @@ -31,7 +31,7 @@ import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "is.single", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) -public abstract class IsSingle extends RBuiltinNode { +public abstract class IsSingle extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(IsSingle.class); @@ -40,7 +40,7 @@ public abstract class IsSingle extends RBuiltinNode { @Specialization protected Object isSingle(@SuppressWarnings("unused") Object x) { - throw RError.error(this, RError.Message.UNIMPLEMENTED_TYPE_IN_R, "single"); + throw error(RError.Message.UNIMPLEMENTED_TYPE_IN_R, "single"); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java index 4c096d94e544f306d1444830bd1abf3bd7affa2e..74152f23bf2199922819321a77e4e70350476f6c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java @@ -62,18 +62,17 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; /** * Handles all builtin functions of the form {@code is.xxx}, where is {@code xxx} is a "type". */ public class IsTypeFunctions { - protected abstract static class MissingAdapter extends RBuiltinNode { + protected abstract static class MissingAdapter extends RBuiltinNode.Arg1 { protected static Casts createCasts(Class<? extends MissingAdapter> extCls) { Casts casts = new Casts(extCls); - casts.arg("x").mustNotBeMissing((RBaseNode) null, RError.Message.ARGUMENT_MISSING, "x"); + casts.arg("x").mustNotBeMissing(RError.Message.ARGUMENT_MISSING, "x"); return casts; } } @@ -554,7 +553,7 @@ public class IsTypeFunctions { } @RBuiltin(name = "is.vector", kind = INTERNAL, parameterNames = {"x", "mode"}, behavior = PURE) - public abstract static class IsVector extends RBuiltinNode { + public abstract static class IsVector extends RBuiltinNode.Arg2 { private final ConditionProfile attrNull = ConditionProfile.createBinaryProfile(); private final ConditionProfile attrEmpty = ConditionProfile.createBinaryProfile(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java index cb571f301f697837038db0d26a26d078740e1dfd..4c098438beb3419d62b138551c798ec9f2a3084a 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java @@ -44,10 +44,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.ops.BinaryCompare; -@RBuiltin(name = "is.unsorted", kind = INTERNAL, parameterNames = {"x", "strictly"}, behavior = PURE) // TODO support strictly // TODO support lists -public abstract class IsUnsorted extends RBuiltinNode { +@RBuiltin(name = "is.unsorted", kind = INTERNAL, parameterNames = {"x", "strictly"}, behavior = PURE) +public abstract class IsUnsorted extends RBuiltinNode.Arg2 { @Child private BinaryMapBooleanFunctionNode ge = new BinaryMapBooleanFunctionNode(BinaryCompare.GREATER_EQUAL.createOperation()); @Child private BinaryMapBooleanFunctionNode gt = new BinaryMapBooleanFunctionNode(BinaryCompare.GREATER_THAN.createOperation()); @@ -56,7 +56,7 @@ public abstract class IsUnsorted extends RBuiltinNode { static { Casts casts = new Casts(IsUnsorted.class); - casts.arg("strictly").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).notNA().map(toBoolean()); + casts.arg("strictly").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java index 1a27658726297e3ad2473785115c172a18586063..d1515e966da7dcce1c09cd5c630367d32a2f5a78 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java @@ -13,9 +13,14 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.dimEq; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.dimGt; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gt; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.matrix; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.not; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.or; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.squareMatrix; @@ -30,7 +35,6 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode; @@ -38,11 +42,12 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNa import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode; +import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.unary.CastDoubleNode; import com.oracle.truffle.r.nodes.unary.CastDoubleNodeGen; import com.oracle.truffle.r.runtime.RAccuracyInfo; -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.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RComplexVector; @@ -67,35 +72,30 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; */ public class LaFunctions { - protected abstract static class Adapter extends RBuiltinNode { - @Child protected LapackRFFI.LapackRFFINode lapackRFFINode = RFFIFactory.getRFFI().getLapackRFFI().createLapackRFFINode(); - } - @RBuiltin(name = "La_version", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) - public abstract static class Version extends Adapter { + public abstract static class Version extends RBuiltinNode.Arg0 { + @Child LapackRFFI.IlaverNode ilaverNode = RFFIFactory.getRFFI().getLapackRFFI().createIlaverNode(); + @Specialization @TruffleBoundary protected String doVersion() { int[] version = new int[3]; - lapackRFFINode.ilaver(version); + ilaverNode.execute(version); return version[0] + "." + version[1] + "." + version[2]; } } - private abstract static class RsgAdapter extends Adapter { - protected static final String[] NAMES = new String[]{"values", "vectors"}; - protected final BranchProfile errorProfile = BranchProfile.create(); + protected static final String[] NAMES = new String[]{"values", "vectors"}; - protected static Casts createCasts(Class<? extends RsgAdapter> extClass) { - Casts casts = new Casts(extClass); - casts.arg("matrix").asDoubleVector(false, true, false).mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_NUMERIC, "x"); - casts.arg("onlyValues").defaultError(RError.Message.INVALID_ARGUMENT, "only.values").asLogicalVector().findFirst().notNA().map(toBoolean()); - return casts; - } + protected static Casts createCasts(Class<? extends RBuiltinNode> extClass) { + Casts casts = new Casts(extClass); + casts.arg("matrix").asDoubleVector(false, true, false).mustBe(squareMatrix(), Message.MUST_BE_SQUARE_NUMERIC, "x"); + casts.arg("onlyValues").defaultError(Message.INVALID_ARGUMENT, "only.values").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); + return casts; } @RBuiltin(name = "La_rg", kind = INTERNAL, parameterNames = {"matrix", "onlyValues"}, behavior = PURE) - public abstract static class Rg extends RsgAdapter { + public abstract static class Rg extends RBuiltinNode.Arg2 { private final ConditionProfile hasComplexValues = ConditionProfile.createBinaryProfile(); @@ -104,12 +104,13 @@ public class LaFunctions { } @Specialization - protected Object doRg(RDoubleVector matrix, boolean onlyValues, - @Cached("create()") GetDimAttributeNode getDimsNode) { + protected Object doRg(RAbstractDoubleVector matrix, boolean onlyValues, + @Cached("create()") GetDimAttributeNode getDimsNode, + @Cached("create()") LapackRFFI.DgeevNode dgeevNode) { int[] dims = getDimsNode.getDimensions(matrix); // copy array component of matrix as Lapack destroys it int n = dims[0]; - double[] a = matrix.getDataCopy(); + double[] a = matrix.materialize().getDataCopy(); char jobVL = 'N'; char jobVR = 'N'; boolean vectors = !onlyValues; @@ -123,18 +124,16 @@ public class LaFunctions { double[] wi = new double[n]; double[] work = new double[1]; // ask for optimal size of work array - int info = lapackRFFINode.dgeev(jobVL, jobVR, n, a, n, wr, wi, left, n, right, n, work, -1); + int info = dgeevNode.execute(jobVL, jobVR, n, a, n, wr, wi, left, n, right, n, work, -1); if (info != 0) { - errorProfile.enter(); - throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dgeev"); + throw error(Message.LAPACK_ERROR, info, "dgeev"); } // now allocate work array and make the actual call int lwork = (int) work[0]; work = new double[lwork]; - info = lapackRFFINode.dgeev(jobVL, jobVR, n, a, n, wr, wi, left, n, right, n, work, lwork); + info = dgeevNode.execute(jobVL, jobVR, n, a, n, wr, wi, left, n, right, n, work, lwork); if (info != 0) { - errorProfile.enter(); - throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dgeev"); + throw error(Message.LAPACK_ERROR, info, "dgeev"); } // result is a list containing "values" and "vectors" (unless only.values is TRUE) boolean complexValues = false; @@ -196,15 +195,16 @@ public class LaFunctions { } @RBuiltin(name = "La_rs", kind = INTERNAL, parameterNames = {"matrix", "onlyValues"}, behavior = PURE) - public abstract static class Rs extends RsgAdapter { + public abstract static class Rs extends RBuiltinNode.Arg2 { static { createCasts(Rs.class); } @Specialization - protected Object doRs(RDoubleVector matrix, boolean onlyValues, - @Cached("create()") GetDimAttributeNode getDimsNode) { + protected Object doRs(RAbstractDoubleVector matrix, boolean onlyValues, + @Cached("create()") GetDimAttributeNode getDimsNode, + @Cached("create()") LapackRFFI.DsyevrNode dsyevrNode) { int[] dims = getDimsNode.getDimensions(matrix); int n = dims[0]; char jobv = onlyValues ? 'N' : 'V'; @@ -215,7 +215,7 @@ public class LaFunctions { int il = 0; int iu = 0; double abstol = 0.0; - double[] x = matrix.getDataCopy(); + double[] x = matrix.materialize().getDataCopy(); double[] values = new double[n]; @@ -229,19 +229,17 @@ public class LaFunctions { int[] isuppz = new int[2 * n]; double[] work = new double[1]; int[] iwork = new int[1]; - int info = lapackRFFINode.dsyevr(jobv, range, uplo, n, x, n, vl, vu, il, iu, abstol, m, values, z, n, isuppz, work, lwork, iwork, liwork); + int info = dsyevrNode.execute(jobv, range, uplo, n, x, n, vl, vu, il, iu, abstol, m, values, z, n, isuppz, work, lwork, iwork, liwork); if (info != 0) { - errorProfile.enter(); - throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dysevr"); + throw error(Message.LAPACK_ERROR, info, "dysevr"); } lwork = (int) work[0]; liwork = iwork[0]; work = new double[lwork]; iwork = new int[liwork]; - info = lapackRFFINode.dsyevr(jobv, range, uplo, n, x, n, vl, vu, il, iu, abstol, m, values, z, n, isuppz, work, lwork, iwork, liwork); + info = dsyevrNode.execute(jobv, range, uplo, n, x, n, vl, vu, il, iu, abstol, m, values, z, n, isuppz, work, lwork, iwork, liwork); if (info != 0) { - errorProfile.enter(); - throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dysevr"); + throw error(Message.LAPACK_ERROR, info, "dysevr"); } Object[] data = new Object[onlyValues ? 1 : 2]; RStringVector names; @@ -258,46 +256,39 @@ public class LaFunctions { } @RBuiltin(name = "La_qr", kind = INTERNAL, parameterNames = {"in"}, behavior = PURE) - public abstract static class Qr extends Adapter { + public abstract static class Qr extends RBuiltinNode.Arg1 { @CompilationFinal private static final String[] NAMES = new String[]{"qr", "rank", "qraux", "pivot"}; - private final BranchProfile errorProfile = BranchProfile.create(); - static { Casts casts = new Casts(Qr.class); - casts.arg("in").asDoubleVector(false, true, false).mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "a"); + casts.arg("in").asDoubleVector(false, true, false).mustBe(matrix(), Message.MUST_BE_NUMERIC_MATRIX, "a"); } @Specialization protected RList doQr(RAbstractDoubleVector aIn, @Cached("create()") GetDimAttributeNode getDimsNode, - @Cached("create()") SetDimAttributeNode setDimsNode) { + @Cached("create()") SetDimAttributeNode setDimsNode, + @Cached("create()") LapackRFFI.Dgeqp3Node dgeqp3Node) { // This implementation is sufficient for B25 matcal-5. - if (!(aIn instanceof RDoubleVector)) { - RError.nyi(this, "non-real vectors not supported (yet)"); - } - RDoubleVector daIn = (RDoubleVector) aIn; - int[] dims = getDimsNode.getDimensions(daIn); + int[] dims = getDimsNode.getDimensions(aIn); // copy array component of matrix as Lapack destroys it int n = dims[0]; int m = dims[1]; - double[] a = daIn.getDataCopy(); + double[] a = aIn.materialize().getDataCopy(); int[] jpvt = new int[n]; double[] tau = new double[m < n ? m : n]; double[] work = new double[1]; // ask for optimal size of work array - int info = lapackRFFINode.dgeqp3(m, n, a, m, jpvt, tau, work, -1); + int info = dgeqp3Node.execute(m, n, a, m, jpvt, tau, work, -1); if (info < 0) { - errorProfile.enter(); - throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dgeqp3"); + throw error(Message.LAPACK_ERROR, info, "dgeqp3"); } int lwork = (int) work[0]; work = new double[lwork]; - info = lapackRFFINode.dgeqp3(m, n, a, m, jpvt, tau, work, lwork); + info = dgeqp3Node.execute(m, n, a, m, jpvt, tau, work, lwork); if (info < 0) { - errorProfile.enter(); - throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dgeqp3"); + throw error(Message.LAPACK_ERROR, info, "dgeqp3"); } Object[] data = new Object[4]; // TODO check complete @@ -313,9 +304,7 @@ public class LaFunctions { } @RBuiltin(name = "qr_coef_real", kind = INTERNAL, parameterNames = {"q", "b"}, behavior = PURE) - public abstract static class QrCoefReal extends Adapter { - - private final BranchProfile errorProfile = BranchProfile.create(); + public abstract static class QrCoefReal extends RBuiltinNode.Arg2 { private static final char SIDE = 'L'; private static final char TRANS = 'T'; @@ -323,13 +312,15 @@ public class LaFunctions { static { Casts casts = new Casts(QrCoefReal.class); casts.arg("q").mustBe(instanceOf(RList.class)); - casts.arg("b").asDoubleVector(false, true, false).mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "b"); + casts.arg("b").asDoubleVector(false, true, false).mustBe(matrix(), Message.MUST_BE_NUMERIC_MATRIX, "b"); } @Specialization - protected RDoubleVector doQrCoefReal(RList qIn, RDoubleVector bIn, + protected RDoubleVector doQrCoefReal(RList qIn, RAbstractDoubleVector bIn, @Cached("create()") GetDimAttributeNode getBDimsNode, - @Cached("create()") GetDimAttributeNode getQDimsNode) { + @Cached("create()") GetDimAttributeNode getQDimsNode, + @Cached("create()") LapackRFFI.DormqrNode dormqrNode, + @Cached("create()") LapackRFFI.DtrtrsNode dtrtrsNode) { // If bIn was coerced this extra copy is unnecessary RDoubleVector b = (RDoubleVector) bIn.copy(); @@ -342,8 +333,7 @@ public class LaFunctions { int[] qrDims = getQDimsNode.getDimensions(qr); int n = qrDims[0]; if (bDims[0] != n) { - errorProfile.enter(); - throw RError.error(this, RError.Message.RHS_SHOULD_HAVE_ROWS, n, bDims[0]); + throw error(Message.RHS_SHOULD_HAVE_ROWS, n, bDims[0]); } int nrhs = bDims[1]; double[] work = new double[1]; @@ -353,22 +343,19 @@ public class LaFunctions { // we work directly in the internal data of b double[] bData = b.getDataWithoutCopying(); // ask for optimal size of work array - int info = lapackRFFINode.dormqr(SIDE, TRANS, n, nrhs, k, qrData, n, tauData, bData, n, work, -1); + int info = dormqrNode.execute(SIDE, TRANS, n, nrhs, k, qrData, n, tauData, bData, n, work, -1); if (info < 0) { - errorProfile.enter(); - throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dormqr"); + throw error(Message.LAPACK_ERROR, info, "dormqr"); } int lwork = (int) work[0]; work = new double[lwork]; - info = lapackRFFINode.dormqr(SIDE, TRANS, n, nrhs, k, qrData, n, tauData, bData, n, work, lwork); + info = dormqrNode.execute(SIDE, TRANS, n, nrhs, k, qrData, n, tauData, bData, n, work, lwork); if (info < 0) { - errorProfile.enter(); - throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dormqr"); + throw error(Message.LAPACK_ERROR, info, "dormqr"); } - info = lapackRFFINode.dtrtrs('U', 'N', 'N', k, nrhs, qrData, n, bData, n); + info = dtrtrsNode.execute('U', 'N', 'N', k, nrhs, qrData, n, bData, n); if (info < 0) { - errorProfile.enter(); - throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dtrtrs"); + throw error(Message.LAPACK_ERROR, info, "dtrtrs"); } // TODO check complete return b; @@ -376,12 +363,11 @@ public class LaFunctions { } @RBuiltin(name = "det_ge_real", kind = INTERNAL, parameterNames = {"a", "uselog"}, behavior = PURE) - public abstract static class DetGeReal extends Adapter { + public abstract static class DetGeReal extends RBuiltinNode.Arg2 { private static final RStringVector NAMES_VECTOR = RDataFactory.createStringVector(new String[]{"modulus", "sign"}, RDataFactory.COMPLETE_VECTOR); private static final RStringVector DET_CLASS = RDataFactory.createStringVector(new String[]{"det"}, RDataFactory.COMPLETE_VECTOR); - private final BranchProfile errorProfile = BranchProfile.create(); private final ConditionProfile infoGreaterZero = ConditionProfile.createBinaryProfile(); private final ConditionProfile doUseLog = ConditionProfile.createBinaryProfile(); private final NACheck naCheck = NACheck.create(); @@ -390,25 +376,26 @@ public class LaFunctions { static { Casts casts = new Casts(DetGeReal.class); - casts.arg("a").asDoubleVector(false, true, false).mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_MATRIX, "a"); + casts.arg("a").asDoubleVector(false, true, false).mustBe(matrix(), Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(squareMatrix(), Message.MUST_BE_SQUARE_MATRIX, "a"); - casts.arg("uselog").defaultError(RError.Message.MUST_BE_LOGICAL, "logarithm").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("uselog").defaultError(Message.MUST_BE_LOGICAL, "logarithm").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } @Specialization - protected RList doDetGeReal(RDoubleVector aIn, boolean useLog, - @Cached("create()") GetDimAttributeNode getDimsNode) { + + protected RList doDetGeReal(RAbstractDoubleVector aIn, boolean useLog, + @Cached("create()") GetDimAttributeNode getDimsNode, + @Cached("create()") LapackRFFI.DgetrfNode dgetrfNode) { RDoubleVector a = (RDoubleVector) aIn.copy(); int[] aDims = getDimsNode.getDimensions(aIn); int n = aDims[0]; int[] ipiv = new int[n]; double modulus = 0; double[] aData = a.getDataWithoutCopying(); - int info = lapackRFFINode.dgetrf(n, n, aData, n, ipiv); + int info = dgetrfNode.execute(n, n, aData, n, ipiv); int sign = 1; if (info < 0) { - errorProfile.enter(); - throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dgetrf"); + throw error(Message.LAPACK_ERROR, info, "dgetrf"); } else if (infoGreaterZero.profile(info > 0)) { modulus = useLog ? Double.NEGATIVE_INFINITY : 0; } else { @@ -458,9 +445,8 @@ public class LaFunctions { } @RBuiltin(name = "La_chol", kind = INTERNAL, parameterNames = {"a", "pivot", "tol"}, behavior = PURE) - public abstract static class LaChol extends Adapter { + public abstract static class LaChol extends RBuiltinNode.Arg3 { - private final BranchProfile errorProfile = BranchProfile.create(); private final ConditionProfile noPivot = ConditionProfile.createBinaryProfile(); @Child private SetFixedAttributeNode setPivotAttrNode = SetFixedAttributeNode.create("pivot"); @@ -468,19 +454,21 @@ public class LaFunctions { static { Casts casts = new Casts(LaChol.class); - casts.arg("a").asDoubleVector(false, true, false).mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_MATRIX, "a").mustBe( - dimGt(1, 0), RError.Message.DIMS_GT_ZERO, "a"); + casts.arg("a").asDoubleVector(false, true, false).mustBe(matrix(), Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(squareMatrix(), Message.MUST_BE_SQUARE_MATRIX, "a").mustBe( + dimGt(1, 0), Message.DIMS_GT_ZERO, "a"); - casts.arg("pivot").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("pivot").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); casts.arg("tol").asDoubleVector().findFirst(RRuntime.DOUBLE_NA); } @Specialization - protected RDoubleVector doDetGeReal(RDoubleVector aIn, boolean piv, double tol, + protected RDoubleVector doDetGeReal(RAbstractDoubleVector aIn, boolean piv, double tol, @Cached("create()") GetDimAttributeNode getDimsNode, @Cached("create()") SetDimNamesAttributeNode setDimNamesNode, - @Cached("create()") GetDimNamesAttributeNode getDimNamesNode) { + @Cached("create()") GetDimNamesAttributeNode getDimNamesNode, + @Cached("create()") LapackRFFI.DpotrfNode dpotrfNode, + @Cached("create()") LapackRFFI.DpstrfNode dpstrfNode) { RDoubleVector a = (RDoubleVector) aIn.copy(); int[] aDims = getDimsNode.getDimensions(aIn); int n = aDims[0]; @@ -494,21 +482,19 @@ public class LaFunctions { } int info; if (noPivot.profile(!piv)) { - info = lapackRFFINode.dpotrf('U', m, aData, m); + info = dpotrfNode.execute('U', m, aData, m); if (info != 0) { - errorProfile.enter(); // TODO informative error message (aka GnuR) - throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dpotrf"); + throw error(Message.LAPACK_ERROR, info, "dpotrf"); } } else { int[] ipiv = new int[m]; double[] work = new double[2 * m]; int[] rank = new int[1]; - info = lapackRFFINode.dpstrf('U', n, aData, n, ipiv, rank, tol, work); + info = dpstrfNode.execute('U', n, aData, n, ipiv, rank, tol, work); if (info != 0) { - errorProfile.enter(); // TODO informative error message (aka GnuR) - throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dpotrf"); + throw error(Message.LAPACK_ERROR, info, "dpotrf"); } setPivotAttrNode.execute(a, RRuntime.asLogical(piv)); setRankAttrNode.execute(a, rank[0]); @@ -526,8 +512,57 @@ public class LaFunctions { } } + @RBuiltin(name = "La_chol2inv", kind = INTERNAL, parameterNames = {"a", "size"}, behavior = PURE) + public abstract static class LaChol2Inv extends RBuiltinNode.Arg2 { + + @Child private SetFixedAttributeNode setPivotAttrNode = SetFixedAttributeNode.create("pivot"); + @Child private SetFixedAttributeNode setRankAttrNode = SetFixedAttributeNode.create("rank"); + + static { + Casts casts = new Casts(LaChol2Inv.class); + casts.arg("a").asDoubleVector(false, true, false).mustBe(matrix(), Message.MUST_BE_NUMERIC_MATRIX, "a"); + casts.arg("size").asIntegerVector().mustBe(notEmpty()).findFirst().mustBe(gt(0), Message.MUST_BE_POSITIVE_INT); + } + + @Specialization + protected RDoubleVector chol2inv(RAbstractDoubleVector a, int size, + @Cached("create()") GetDimAttributeNode getDimsNode, + @Cached("create()") LapackRFFI.DpotriNode dpotriNode) { + + int[] aDims = getDimsNode.getDimensions(a); + int m = aDims[0]; + int n = aDims[1]; + + if (size > n) { + throw error(Message.CANNOT_EXCEED_X, "size", "ncol", n); + } + if (size > m) { + throw error(Message.CANNOT_EXCEED_X, "size", "nrow", n); + } + double[] result = new double[size * size]; + for (int j = 0; j < size; j++) { + for (int i = 0; i <= j; i++) { + result[i + j * size] = a.getDataAt(i + j * m); + } + } + int info = dpotriNode.execute('U', size, result, size); + if (info != 0) { + if (info > 0) { + throw error(Message.LAPACK_ZERO_INVERSE, info, info); + } + throw error(Message.LAPACK_INVALID_VALUE, -info, "dpotri"); + } + for (int j = 0; j < size; j++) { + for (int i = j + 1; i < size; i++) { + result[i + j * size] = result[j + i * size]; + } + } + return RDataFactory.createDoubleVector(result, true, new int[]{size, size}); + } + } + @RBuiltin(name = "La_solve", kind = INTERNAL, parameterNames = {"a", "bin", "tolin"}, behavior = PURE) - public abstract static class LaSolve extends Adapter { + public abstract static class LaSolve extends RBuiltinNode.Arg3 { @Child private CastDoubleNode castDouble = CastDoubleNodeGen.create(false, false, false); private static Function<RAbstractDoubleVector, Object> getDimVal(int dim) { @@ -536,31 +571,35 @@ public class LaFunctions { static { Casts casts = new Casts(LaSolve.class); - casts.arg("a").mustBe(numericValue()).asVector().mustBe(matrix(), RError.ROOTNODE, RError.Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(not(dimEq(0, 0)), RError.ROOTNODE, - RError.Message.GENERIC, "'a' is 0-diml").mustBe(squareMatrix(), RError.ROOTNODE, RError.Message.MUST_BE_SQUARE_MATRIX_SPEC, "a", getDimVal(0), getDimVal(1)); + casts.arg("a").mustBe(numericValue()).asVector().mustBe(matrix(), Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(not(dimEq(0, 0)), + Message.GENERIC, "'a' is 0-diml").mustBe(squareMatrix(), Message.MUST_BE_SQUARE_MATRIX_SPEC, "a", getDimVal(0), getDimVal(1)); - casts.arg("bin").asDoubleVector(false, true, false).mustBe(or(not(matrix()), not(dimEq(1, 0))), RError.ROOTNODE, RError.Message.GENERIC, "no right-hand side in 'b'"); + casts.arg("bin").returnIf(missingValue().or(nullValue()), emptyDoubleVector()).asDoubleVector(false, true, false).mustBe(or(not(matrix()), not(dimEq(1, 0))), Message.GENERIC, + "no right-hand side in 'b'"); casts.arg("tolin").asDoubleVector().findFirst(RRuntime.DOUBLE_NA); } @Specialization - protected RDoubleVector laSolve(RAbstractVector a, RDoubleVector bin, double tol, + protected RDoubleVector laSolve(RAbstractVector a, RAbstractDoubleVector bin, double tol, @Cached("create()") GetDimAttributeNode getADimsNode, @Cached("create()") GetDimAttributeNode getBinDimsNode, @Cached("create()") SetDimAttributeNode setBDimsNode, @Cached("create()") SetDimNamesAttributeNode setBDimNamesNode, @Cached("create()") GetDimNamesAttributeNode getADimNamesNode, @Cached("create()") GetDimNamesAttributeNode getBinDimNamesNode, - @Cached("create()") SetNamesAttributeNode setNamesNode) { + @Cached("create()") SetNamesAttributeNode setNamesNode, + @Cached("create()") LapackRFFI.DgesvNode dgesvNode, + @Cached("create()") LapackRFFI.DgeconNode dgeconNode, + @Cached("create()") LapackRFFI.DlangeNode dlangeNode) { int[] aDims = getADimsNode.getDimensions(a); int n = aDims[0]; if (n == 0) { - throw RError.error(this, RError.Message.GENERIC, "'a' is 0-diml"); + throw error(Message.GENERIC, "'a' is 0-diml"); } int n2 = aDims[1]; if (n2 != n) { - throw RError.error(this, RError.Message.MUST_BE_SQUARE, "a", n, n2); + throw error(Message.MUST_BE_SQUARE, "a", n, n2); } RList aDn = getADimNamesNode.getDimNames(a); int p; @@ -570,11 +609,11 @@ public class LaFunctions { int[] bDims = getBinDimsNode.getDimensions(bin); p = bDims[1]; if (p == 0) { - throw RError.error(this, RError.Message.GENERIC, "no right-hand side in 'b'"); + throw error(Message.GENERIC, "no right-hand side in 'b'"); } int p2 = bDims[0]; if (p2 != n) { - throw RError.error(this, RError.Message.MUST_BE_SQUARE_COMPATIBLE, "b", p2, p, "a", n, n); + throw error(Message.MUST_BE_SQUARE_COMPATIBLE, "b", p2, p, "a", n, n); } bData = new double[n * p]; b = RDataFactory.createDoubleVector(bData, RDataFactory.COMPLETE_VECTOR); @@ -583,21 +622,17 @@ public class LaFunctions { // This is somewhat odd, but Matrix relies on dropping NULL dimnames if (aDn != null || binDn != null) { // rownames(ans) = colnames(A), colnames(ans) = colnames(Bin) - Object[] bDnData = new Object[2]; - if (aDn != null) { - bDnData[0] = aDn.getDataAt(1); - } - if (binDn != null) { - bDnData[1] = binDn.getDataAt(1); - } - if (bDnData[0] != null || bDnData[1] != null) { + if (aDn != null || binDn != null) { + Object[] bDnData = new Object[2]; + bDnData[0] = aDn == null ? RNull.instance : aDn.getDataAt(1); + bDnData[1] = binDn == null ? RNull.instance : binDn.getDataAt(1); setBDimNamesNode.setDimNames(b, RDataFactory.createList(bDnData)); } } } else { p = 1; if (bin.getLength() != n) { - throw RError.error(this, RError.Message.MUST_BE_SQUARE_COMPATIBLE, "b", bin.getLength(), p, "a", n, n); + throw error(Message.MUST_BE_SQUARE_COMPATIBLE, "b", bin.getLength(), p, "a", n, n); } bData = new double[n]; b = RDataFactory.createDoubleVector(bData, RDataFactory.COMPLETE_VECTOR); @@ -614,24 +649,24 @@ public class LaFunctions { if (a instanceof RAbstractDoubleVector) { System.arraycopy(a.getInternalStore(), 0, avals, 0, n * n); } else { - RDoubleVector aDouble = (RDoubleVector) castDouble.execute(a); + RDoubleVector aDouble = (RDoubleVector) castDouble.doCast(a); assert aDouble != a; avals = aDouble.getInternalStore(); } - int info = lapackRFFINode.dgesv(n, p, avals, n, ipiv, bData, n); + int info = dgesvNode.execute(n, p, avals, n, ipiv, bData, n); if (info < 0) { - RError.error(this, RError.Message.LAPACK_INVALID_VALUE, -info, "dgesv"); + throw error(Message.LAPACK_INVALID_VALUE, -info, "dgesv"); } if (info > 0) { - RError.error(this, RError.Message.LAPACK_EXACTLY_SINGULAR, "dgesv", info, info); + throw error(Message.LAPACK_EXACTLY_SINGULAR, "dgesv", info, info); } if (tol > 0) { - double anorm = lapackRFFINode.dlange('1', n, n, avals, n, null); + double anorm = dlangeNode.execute('1', n, n, avals, n, null); double[] work = new double[4 * n]; double[] rcond = new double[1]; - lapackRFFINode.dgecon('1', n, avals, n, anorm, rcond, work, ipiv); + dgeconNode.execute('1', n, avals, n, anorm, rcond, work, ipiv); if (rcond[0] < tol) { - RError.error(this, RError.Message.SYSTEM_COMP_SINGULAR, rcond[0]); + throw error(Message.SYSTEM_COMP_SINGULAR, rcond[0]); } } return b; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java index a3bb7941e9bcef3db6f36feceea98a7c45e1d417..0e8c9f0639a7a21082dbdba6dcedeabae9d49cc4 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java @@ -47,6 +47,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode; @@ -63,7 +64,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; * See the comment in {@link VApply} regarding "...". */ @RBuiltin(name = "lapply", kind = INTERNAL, parameterNames = {"X", "FUN"}, splitCaller = true, behavior = COMPLEX) -public abstract class Lapply extends RBuiltinNode { +public abstract class Lapply extends RBuiltinNode.Arg2 { private static final Source CALL_SOURCE = RSource.fromTextInternal("FUN(X[[i]], ...)", RSource.Internal.LAPPLY); @@ -74,8 +75,8 @@ public abstract class Lapply extends RBuiltinNode { // to make conversion of X parameter 100% correct, we'd need to match semantics of // asVector() to whatever GNU R is doing there; still this can be a problem only if the // internal is called directly (otherwise, it's guaranteed that it's a vector) - casts.arg("X").asVector(); - casts.arg("FUN").mustBe(instanceOf(RFunction.class), RError.NO_CALLER, RError.Message.APPLY_NON_FUNCTION); + casts.arg("X").returnIf(instanceOf(RAbstractVector.class).not()).asVector(false); + casts.arg("FUN").mustBe(instanceOf(RFunction.class), RError.Message.APPLY_NON_FUNCTION); } @Specialization @@ -86,6 +87,12 @@ public abstract class Lapply extends RBuiltinNode { return RDataFactory.createList(result, getNamesNode.getNames(vec)); } + @Specialization + protected Object lapply(VirtualFrame frame, Object x, RFunction fun) { + Object[] result = lapply.execute(frame, x, fun); + return RDataFactory.createList(result); + } + private static final class ExtractElementInternal extends RSourceSectionNode implements RSyntaxCall { @Child private ExtractVectorNode extractElementNode = ExtractVectorNodeGen.create(ElementAccessMode.SUBSCRIPT, false); @@ -101,7 +108,7 @@ public abstract class Lapply extends RBuiltinNode { @Override public Object execute(VirtualFrame frame) { try { - return extractElementNode.apply(frame, frame.getObject(vectorSlot), new Object[]{frame.getInt(indexSlot)}, RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_TRUE); + return extractElementNode.apply(frame, FrameSlotChangeMonitor.getObject(vectorSlot, frame), new Object[]{frame.getInt(indexSlot)}, RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_TRUE); } catch (FrameSlotTypeException e) { CompilerDirectives.transferToInterpreter(); throw RInternalError.shouldNotReachHere("frame type mismatch in lapply"); @@ -132,11 +139,11 @@ public abstract class Lapply extends RBuiltinNode { public abstract Object[] execute(VirtualFrame frame, Object vector, RFunction function); protected static FrameSlot createIndexSlot(Frame frame) { - return frame.getFrameDescriptor().findOrAddFrameSlot(INDEX_NAME, FrameSlotKind.Int); + return FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), INDEX_NAME, FrameSlotKind.Int); } protected static FrameSlot createVectorSlot(Frame frame) { - return frame.getFrameDescriptor().findOrAddFrameSlot(VECTOR_NAME, FrameSlotKind.Object); + return FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), VECTOR_NAME, FrameSlotKind.Object); } @Specialization @@ -148,7 +155,7 @@ public abstract class Lapply extends RBuiltinNode { @Cached("createCallNode(vectorSlot, indexSlot)") RCallNode firstCallNode, @Cached("createCallNode(vectorSlot, indexSlot)") RCallNode callNode) { // TODO: R switches to double if x.getLength() is greater than 2^31-1 - frame.setObject(vectorSlot, vector); + FrameSlotChangeMonitor.setObject(frame, vectorSlot, vector); int length = lengthNode.executeInteger(frame, vector); Object[] result = new Object[length]; if (length > 0) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Length.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Length.java index df92d3e9fa020cb62fbb1f1212cde43b66c9597d..2acf8880970607484d5a3a06dfd7ade019115ea1 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Length.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Length.java @@ -34,7 +34,7 @@ import com.oracle.truffle.r.nodes.control.RLengthNode; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "length", kind = PRIMITIVE, dispatch = INTERNAL_GENERIC, parameterNames = {"x"}, behavior = PURE) -public abstract class Length extends RBuiltinNode { +public abstract class Length extends RBuiltinNode.Arg1 { public abstract int executeInt(VirtualFrame frame, Object vector); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java index 3b1cff197bee5ae5be5da149591f407b40afd91a..69e7498c34e5ed7a06a1bc8be2d2797ba4b76620 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java @@ -38,7 +38,6 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.control.RLengthNode; -import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RIntVector; @@ -47,14 +46,14 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "lengths", kind = INTERNAL, parameterNames = {"x", "use.names"}, behavior = PURE) -public abstract class Lengths extends RBuiltinNode { +public abstract class Lengths extends RBuiltinNode.Arg2 { @Child private RLengthNode lengthNode; static { Casts casts = new Casts(Lengths.class); - casts.arg("x").defaultError(RError.SHOW_CALLER, X_LIST_ATOMIC).allowNull().mustBe(abstractVectorValue()); - casts.arg("use.names").mustBe(numericValue(), RError.SHOW_CALLER, INVALID_VALUE, "use.names").asLogicalVector().findFirst().map(toBoolean()); + casts.arg("x").defaultError(X_LIST_ATOMIC).allowNull().mustBe(abstractVectorValue()); + casts.arg("use.names").mustBe(numericValue(), INVALID_VALUE, "use.names").asLogicalVector().findFirst().map(toBoolean()); } private void initLengthNode() { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java index dc2757951add8e95c945012a65148b0b2cc3ec3e..b98566310e2335a0f3afe3a2f291415913467458 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.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 @@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.conn.StdConnections; import com.oracle.truffle.r.runtime.data.RNull; @RBuiltin(name = "license", visibility = OFF, aliases = {"licence"}, kind = SUBSTITUTE, parameterNames = {}, behavior = IO) -public abstract class License extends RBuiltinNode { +public abstract class License extends RBuiltinNode.Arg0 { @Specialization @TruffleBoundary @@ -46,7 +46,7 @@ public abstract class License extends RBuiltinNode { try { StdConnections.getStdout().writeString(RRuntime.LICENSE, true); } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); + throw error(RError.Message.GENERIC, ex.getMessage()); } return RNull.instance; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/List2Env.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/List2Env.java index f1ab5acbb72b74e7146af06404d35b25accf3af4..60a62338d6d531bb9243592afa0d452fc68309f1 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/List2Env.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/List2Env.java @@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.env.REnvironment; @RBuiltin(name = "list2env", kind = INTERNAL, parameterNames = {"x", "envir"}, behavior = PURE) -public abstract class List2Env extends RBuiltinNode { +public abstract class List2Env extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(List2Env.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ListBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ListBuiltin.java index e7ffa8d42c2de6915c99b212b0c5fb163ef5556a..dc16026b21480763d246b606c21b49e00d356ee1 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ListBuiltin.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ListBuiltin.java @@ -43,7 +43,7 @@ import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RStringVector; @RBuiltin(name = "list", kind = PRIMITIVE, parameterNames = {"..."}, behavior = PURE) -public abstract class ListBuiltin extends RBuiltinNode { +public abstract class ListBuiltin extends RBuiltinNode.Arg1 { protected static final int CACHE_LIMIT = 2; protected static final int MAX_SHARE_OBJECT_NODES = 16; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java index 462f900017a3c52b5ccfb872e0bb94b38b29d762..9d7e4eec318c1bfc3eecdda2e843d47cff737805 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java @@ -13,7 +13,6 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; @@ -28,15 +27,12 @@ import java.io.IOException; 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.frame.VirtualFrame; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.builtin.base.SerializeFunctions.Adapter; import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode; 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.RSerialize; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -55,7 +51,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; public class LoadSaveFunctions { @RBuiltin(name = "loadFromConn2", visibility = OFF, kind = INTERNAL, parameterNames = {"con", "envir", "verbose"}, behavior = IO) - public abstract static class LoadFromConn2 extends RBuiltinNode { + public abstract static class LoadFromConn2 extends RBuiltinNode.Arg3 { private final NACheck naCheck = NACheck.create(); @@ -78,7 +74,7 @@ public class LoadSaveFunctions { return RDataFactory.createEmptyStringVector(); } if (!(o instanceof RPairList)) { - throw RError.error(this, RError.Message.GENERIC, "loaded data is not in pair list form"); + throw error(RError.Message.GENERIC, "loaded data is not in pair list form"); } RPairList vars = (RPairList) o; @@ -102,18 +98,18 @@ public class LoadSaveFunctions { return RDataFactory.createStringVector(data, naCheck.neverSeenNA()); } else { - throw RError.error(this, RError.Message.GENERIC, "the input does not start with a magic number compatible with loading from a connection"); + throw error(RError.Message.GENERIC, "the input does not start with a magic number compatible with loading from a connection"); } } catch (IOException iox) { - throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_READING_CONNECTION, iox.getMessage()); + throw error(RError.Message.ERROR_READING_CONNECTION, iox.getMessage()); } catch (PutException px) { - throw RError.error(RError.SHOW_CALLER, px); + throw error(px); } } } @RBuiltin(name = "load", visibility = OFF, kind = INTERNAL, parameterNames = {"file", "envir"}, behavior = IO) - public abstract static class Load extends RBuiltinNode { + public abstract static class Load extends RBuiltinNode.Arg2 { // now deprecated but still used by some packages static { @@ -140,16 +136,16 @@ public class LoadSaveFunctions { int magic = readMagic(bs); switch (magic) { case R_MAGIC_EMPTY: - throw RError.error(this, RError.Message.MAGIC_EMPTY); + throw error(RError.Message.MAGIC_EMPTY); case R_MAGIC_TOONEW: - throw RError.error(this, RError.Message.MAGIC_TOONEW); + throw error(RError.Message.MAGIC_TOONEW); case R_MAGIC_CORRUPT: - throw RError.error(this, RError.Message.MAGIC_CORRUPT); + throw error(RError.Message.MAGIC_CORRUPT); default: } } catch (IOException ex) { - throw RError.error(this, RError.Message.FILE_OPEN_ERROR); + throw error(RError.Message.FILE_OPEN_ERROR); } throw RError.nyi(this, "load"); } @@ -189,7 +185,7 @@ public class LoadSaveFunctions { } @RBuiltin(name = "saveToConn", visibility = OFF, kind = INTERNAL, parameterNames = {"list", "con", "ascii", "version", "environment", "eval.promises"}, behavior = IO) - public abstract static class SaveToConn extends Adapter { + public abstract static class SaveToConn extends RBuiltinNode.Arg6 { private static final String ASCII_HEADER = "RDA2\n"; private static final String XDR_HEADER = "RDX2\n"; @@ -197,14 +193,14 @@ public class LoadSaveFunctions { Casts casts = new Casts(SaveToConn.class); casts.arg("list").mustBe(stringValue()).asStringVector(); ConnectionFunctions.CastsHelper.connection(casts); - casts.arg("ascii").mustBe(logicalValue(), RError.Message.ASCII_NOT_LOGICAL); - casts.arg("version").allowNull().mustBe(integerValue()); + casts.arg("ascii").mustBe(logicalValue(), RError.Message.ASCII_NOT_LOGICAL).asLogicalVector().findFirst().map(toBoolean()); + casts.arg("version").allowNull().asIntegerVector().findFirstOrNull(); casts.arg("environment").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class)); - casts.arg("eval.promises").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("eval.promises").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } @Specialization - protected Object saveToConn(VirtualFrame frame, RAbstractStringVector list, int con, byte asciiLogical, @SuppressWarnings("unused") RNull version, REnvironment envir, boolean evalPromises, + protected Object saveToConn(VirtualFrame frame, RAbstractStringVector list, int con, boolean ascii, @SuppressWarnings("unused") RNull version, REnvironment envir, boolean evalPromises, @Cached("new()") PromiseCheckHelperNode promiseHelper) { RPairList prev = null; Object toSave = RNull.instance; @@ -212,7 +208,7 @@ public class LoadSaveFunctions { String varName = list.getDataAt(i); Object value = envir.get(varName); if (value == null) { - throw RError.error(this, RError.Message.UNKNOWN_OBJECT, varName); + throw error(RError.Message.UNKNOWN_OBJECT, varName); } if (evalPromises) { value = promiseHelper.checkEvaluate(frame, value); @@ -226,7 +222,6 @@ public class LoadSaveFunctions { } prev = pl; } - boolean ascii = RRuntime.fromLogical(asciiLogical); doSaveConn(toSave, RConnection.fromIndex(con), ascii); return RNull.instance; } @@ -235,22 +230,22 @@ public class LoadSaveFunctions { private void doSaveConn(Object toSave, RConnection conn, boolean ascii) { try (RConnection openConn = conn.forceOpen(ascii ? "wt" : "wb")) { if (!openConn.canWrite()) { - throw RError.error(this, RError.Message.CONNECTION_NOT_OPEN_WRITE); + throw error(RError.Message.CONNECTION_NOT_OPEN_WRITE); } if (!ascii && openConn.isTextMode()) { - throw RError.error(this, RError.Message.CONN_XDR); + throw error(RError.Message.CONN_XDR); } - openConn.writeChar(ascii ? ASCII_HEADER : XDR_HEADER, 0, "", false); + openConn.writeChar(ascii ? ASCII_HEADER : XDR_HEADER, 0, null, false); RSerialize.serialize(openConn, toSave, ascii ? RSerialize.ASCII : RSerialize.XDR, RSerialize.DEFAULT_VERSION, null); } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); + throw error(RError.Message.GENERIC, ex.getMessage()); } } @SuppressWarnings("unused") - @Fallback - protected Object saveToConn(Object list, Object con, Object ascii, Object version, Object envir, Object evaPromises) { - throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); + @Specialization + protected Object saveToConn(VirtualFrame frame, RAbstractStringVector list, int con, boolean ascii, int version, REnvironment envir, boolean evalPromises) { + throw error(RError.Message.INVALID_ARG_TYPE, 5); // [TODO] implement "version" support } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java index 29231259c8f30c438b3372b0a2074bc5bec39946..aae947e9a61c705ef829d0a05a3e7835369b7eac 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java @@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; -import static com.oracle.truffle.r.runtime.RError.NO_CALLER; import static com.oracle.truffle.r.runtime.RError.Message.ARGUMENT_NOT_CHAR_VECTOR; import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ARGUMENT; import static com.oracle.truffle.r.runtime.RError.Message.INVALID_VALUE; @@ -53,7 +52,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; public class LocaleFunctions { @RBuiltin(name = "Sys.getlocale", kind = INTERNAL, parameterNames = {"category"}, behavior = READS_STATE) - public abstract static class GetLocale extends RBuiltinNode { + public abstract static class GetLocale extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(GetLocale.class); @@ -91,7 +90,7 @@ public class LocaleFunctions { } @RBuiltin(name = "Sys.setlocale", kind = INTERNAL, parameterNames = {"category", "locale"}, behavior = MODIFIES_STATE) - public abstract static class SetLocale extends RBuiltinNode { + public abstract static class SetLocale extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(SetLocale.class); @@ -108,7 +107,7 @@ public class LocaleFunctions { } @RBuiltin(name = "Sys.localeconv", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) - public abstract static class LocaleConv extends RBuiltinNode { + public abstract static class LocaleConv extends RBuiltinNode.Arg0 { @Specialization @TruffleBoundary protected Object localeconv() { @@ -118,7 +117,7 @@ public class LocaleFunctions { } @RBuiltin(name = "l10n_info", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) - public abstract static class L10nInfo extends RBuiltinNode { + public abstract static class L10nInfo extends RBuiltinNode.Arg0 { private static final RStringVector NAMES = RDataFactory.createStringVector(new String[]{"MBCS", "UTF-8", "Latin-1"}, RDataFactory.COMPLETE_VECTOR); @Specialization @@ -133,7 +132,7 @@ public class LocaleFunctions { } @RBuiltin(name = "enc2native", kind = PRIMITIVE, parameterNames = "x", behavior = READS_STATE) - public abstract static class Enc2Native extends RBuiltinNode { + public abstract static class Enc2Native extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(Enc2Native.class); @@ -148,7 +147,7 @@ public class LocaleFunctions { } @RBuiltin(name = "enc2utf8", kind = PRIMITIVE, parameterNames = "x", behavior = READS_STATE) - public abstract static class Enc2Utf8 extends RBuiltinNode { + public abstract static class Enc2Utf8 extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(Enc2Utf8.class); @@ -163,7 +162,7 @@ public class LocaleFunctions { } @RBuiltin(name = "bindtextdomain", kind = PRIMITIVE, parameterNames = {"domain", "dirname"}, behavior = READS_STATE) - public abstract static class BindTextDomain extends RBuiltinNode { + public abstract static class BindTextDomain extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(BindTextDomain.class); @@ -184,7 +183,7 @@ public class LocaleFunctions { } private static void category(Casts casts) { - casts.arg("category").mustBe(numericValue(), NO_CALLER, INVALID_ARGUMENT, "category").asIntegerVector().findFirst(); + casts.arg("category").mustBe(numericValue(), INVALID_ARGUMENT, "category").asIntegerVector().findFirst(); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java index e157019c8ea7564e0119b7875b9e47372a949452..4a3a38d7134f8499c65c3460719efd9cdac0439e 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java @@ -28,12 +28,19 @@ import static com.oracle.truffle.r.runtime.RDispatch.MATH_GROUP_GENERIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; +import java.util.Arrays; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; +import com.oracle.truffle.r.nodes.binary.BinaryMapArithmeticFunctionNode; +import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode; import com.oracle.truffle.r.runtime.RError; @@ -41,19 +48,23 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RComplex; +import com.oracle.truffle.r.runtime.data.RComplexVector; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; +import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; +import com.oracle.truffle.r.runtime.ops.na.NACheck; import com.oracle.truffle.r.runtime.ops.na.NAProfile; public class LogFunctions { @RBuiltin(name = "log", kind = PRIMITIVE, parameterNames = {"x", "base"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) - public abstract static class Log extends RBuiltinNode { + public abstract static class Log extends RBuiltinNode.Arg2 { - private final NAProfile naProfile = NAProfile.create(); + private final NAProfile naX = NAProfile.create(); private final BranchProfile nanProfile = BranchProfile.create(); @Override @@ -64,54 +75,156 @@ public class LogFunctions { static { Casts casts = new Casts(Log.class); casts.arg("x").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue())); - casts.arg("base").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue()).asDoubleVector().findFirst(); + casts.arg("base").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue())).mapIf(numericValue(), Predef.asDoubleVector(), + Predef.asComplexVector()).asVector().findFirst(); + } + + static BinaryMapArithmeticFunctionNode createDivNode() { + return new BinaryMapArithmeticFunctionNode(BinaryArithmetic.DIV.createOperation()); + } + + @Specialization + protected double log(byte x, double base, + @Cached("create()") NAProfile naBase) { + if (naX.isNA(x)) { + return RRuntime.DOUBLE_NA; + } + return logb(x, base, naBase); + } + + @Specialization + protected double log(int x, double base, + @Cached("create()") NAProfile naBase) { + if (naX.isNA(x)) { + return RRuntime.DOUBLE_NA; + } + return logb(x, base, naBase); + } + + @Specialization + protected double log(double x, double base, + @Cached("create()") NAProfile naBase) { + if (naX.isNA(x)) { + return RRuntime.DOUBLE_NA; + } + return logb(x, base, naBase); + } + + @Specialization + protected RComplex log(RComplex x, double base, + @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode, + @Cached("create()") NAProfile naBase) { + if (naX.isNA(x)) { + return x; + } + return logb(x, RComplex.valueOf(base, 0), divNode, naBase); } @Specialization - protected double log(int x, double base) { - return logb(x, base); + protected RComplex log(byte x, RComplex base, + @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode, + @Cached("create()") NAProfile naBase) { + if (naX.isNA(x)) { + return RComplex.createNA(); + } + return logb(RComplex.valueOf(x, 0), base, divNode, naBase); } @Specialization - protected double log(double x, double base) { - return logb(x, base); + protected RComplex log(int x, RComplex base, + @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode, + @Cached("create()") NAProfile naBase) { + if (naX.isNA(x)) { + return RComplex.createNA(); + } + return logb(RComplex.valueOf(x, 0), base, divNode, naBase); } @Specialization - protected RDoubleVector log(RAbstractIntVector vector, double base, + protected RComplex log(double x, RComplex base, + @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode, + @Cached("create()") NAProfile naBase) { + if (naX.isNA(x)) { + return RComplex.createNA(); + } + return logb(RComplex.valueOf(x, 0), base, divNode, naBase); + } + + @Specialization + protected RComplex log(RComplex x, RComplex base, + @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode, + @Cached("create()") NAProfile naBase) { + if (naX.isNA(x)) { + return RComplex.createNA(); + } + return logb(x, base, divNode, naBase); + } + + @Specialization(guards = "!isRAbstractComplexVector(vector)") + protected RDoubleVector log(RAbstractVector vector, double base, + @Cached("createClassProfile()") ValueProfile vectorProfile, + @Cached("createBinaryProfile()") ConditionProfile isNAProfile, @Cached("create()") CopyOfRegAttributesNode copyAttrsNode, @Cached("create()") GetNamesAttributeNode getNamesNode, - @Cached("create()") GetDimAttributeNode getDimsNode) { - double[] resultVector = new double[vector.getLength()]; - for (int i = 0; i < vector.getLength(); i++) { - int inputValue = vector.getDataAt(i); - double result = RRuntime.DOUBLE_NA; - if (!naProfile.isNA(inputValue)) { - result = logb(inputValue, base); - } - resultVector[i] = result; - } - return createResult(vector, resultVector, base, copyAttrsNode, getNamesNode, getDimsNode); + @Cached("create()") GetDimAttributeNode getDimsNode, + @Cached("create()") NACheck xNACheck, + @Cached("create()") NACheck baseNACheck) { + RAbstractDoubleVector doubleVector = (RAbstractDoubleVector) vectorProfile.profile(vector).castSafe(RType.Double, isNAProfile); + return logInternal(doubleVector, base, copyAttrsNode, getNamesNode, getDimsNode, xNACheck, baseNACheck); + } + + @Specialization + protected RComplexVector log(RAbstractComplexVector vector, double base, + @Cached("createClassProfile()") ValueProfile vectorProfile, + @Cached("create()") CopyOfRegAttributesNode copyAttrsNode, + @Cached("create()") GetNamesAttributeNode getNamesNode, + @Cached("create()") GetDimAttributeNode getDimsNode, + @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode, + @Cached("create()") NACheck xNACheck, + @Cached("create()") NACheck baseNACheck) { + return logInternal(vectorProfile.profile(vector), RComplex.valueOf(base, 0), divNode, getDimsNode, getNamesNode, copyAttrsNode, xNACheck, baseNACheck); } @Specialization - protected RDoubleVector log(RAbstractDoubleVector vector, double base, + protected RAbstractComplexVector log(RAbstractVector vector, RComplex base, + @Cached("createClassProfile()") ValueProfile vectorProfile, + @Cached("createBinaryProfile()") ConditionProfile isNAProfile, @Cached("create()") CopyOfRegAttributesNode copyAttrsNode, @Cached("create()") GetNamesAttributeNode getNamesNode, - @Cached("create()") GetDimAttributeNode getDimsNode) { - double[] doubleVector = new double[vector.getLength()]; - for (int i = 0; i < vector.getLength(); i++) { - double value = vector.getDataAt(i); - if (!RRuntime.isNA(value)) { - value = logb(value, base); + @Cached("create()") GetDimAttributeNode getDimsNode, + @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode, + @Cached("create()") NACheck xNACheck, + @Cached("create()") NACheck baseNACheck) { + RAbstractComplexVector complexVector = (RAbstractComplexVector) vectorProfile.profile(vector).castSafe(RType.Complex, isNAProfile); + return logInternal(complexVector, base, divNode, getDimsNode, getNamesNode, copyAttrsNode, xNACheck, baseNACheck); + } + + private RDoubleVector logInternal(RAbstractDoubleVector vector, double base, CopyOfRegAttributesNode copyAttrsNode, GetNamesAttributeNode getNamesNode, GetDimAttributeNode getDimsNode, + NACheck xNACheck, NACheck baseNACheck) { + baseNACheck.enable(base); + double[] resultVector = new double[vector.getLength()]; + if (baseNACheck.check(base)) { + Arrays.fill(resultVector, 0, resultVector.length, base); + } else if (Double.isNaN(base)) { + nanProfile.enter(); + Arrays.fill(resultVector, 0, resultVector.length, Double.NaN); + } else { + xNACheck.enable(vector); + RBaseNode[] warningCtx = new RBaseNode[1]; + for (int i = 0; i < vector.getLength(); i++) { + double value = vector.getDataAt(i); + resultVector[i] = xNACheck.check(value) ? RRuntime.DOUBLE_NA : logb(value, base, warningCtx); + } + if (warningCtx[0] != null) { + RError.warning(warningCtx[0], RError.Message.NAN_PRODUCED); } - doubleVector[i] = value; } - return createResult(vector, doubleVector, base, copyAttrsNode, getNamesNode, getDimsNode); + boolean complete = xNACheck.neverSeenNA() && baseNACheck.neverSeenNA(); + return createResult(vector, resultVector, complete, copyAttrsNode, getNamesNode, getDimsNode); } - private double logb(double x, double base) { - if (naProfile.isNA(base)) { + private double logb(double x, double base, NAProfile naBase) { + if (naBase.isNA(base)) { return RRuntime.DOUBLE_NA; } @@ -119,16 +232,119 @@ public class LogFunctions { nanProfile.enter(); return base; } + RBaseNode[] warningCtx = new RBaseNode[1]; + double ret = logb(x, base, warningCtx); + if (warningCtx[0] != null) { + RError.warning(warningCtx[0], RError.Message.NAN_PRODUCED); + } + return ret; + } + + @TruffleBoundary + private double logb(double x, double base, RBaseNode[] warningCtx) { + double logx = Math.log(x); + if (Double.isNaN(logx)) { + warningCtx[0] = this; + } + if (base == Math.E) { + return logx; + } + + double result = logx / Math.log(base); + if (warningCtx[0] == null && Double.isNaN(result)) { + warningCtx[0] = RError.SHOW_CALLER; + } + + return result; + } + + private RComplexVector logInternal(RAbstractComplexVector vector, RComplex base, BinaryMapArithmeticFunctionNode divNode, GetDimAttributeNode getDimsNode, GetNamesAttributeNode getNamesNode, + CopyOfRegAttributesNode copyAttrsNode, NACheck xNACheck, NACheck baseNACheck) { + baseNACheck.enable(base); + double[] complexVector = new double[vector.getLength() * 2]; + if (baseNACheck.check(base)) { + Arrays.fill(complexVector, 0, complexVector.length, RRuntime.DOUBLE_NA); + } else if (Double.isNaN(base.getRealPart()) || Double.isNaN(base.getImaginaryPart())) { + nanProfile.enter(); + Arrays.fill(complexVector, 0, complexVector.length, Double.NaN); + } else { + xNACheck.enable(vector); + boolean seenNaN = false; + for (int i = 0; i < vector.getLength(); i++) { + RComplex value = vector.getDataAt(i); + if (xNACheck.check(value)) { + fill(complexVector, i * 2, value); + } else { + RComplex rc = logb(value, base, divNode, false); + seenNaN = isNaN(rc); + fill(complexVector, i * 2, rc); + } + } + if (seenNaN) { + RError.warning(this, RError.Message.NAN_PRODUCED_IN_FUNCTION, "log"); + } + } + boolean complete = xNACheck.neverSeenNA() && baseNACheck.neverSeenNA(); + return createResult(vector, complexVector, complete, getDimsNode, getNamesNode, copyAttrsNode); + } + + private static void fill(double[] array, int i, RComplex rc) { + array[i] = rc.getRealPart(); + array[i + 1] = rc.getImaginaryPart(); + } + + private RComplex logb(RComplex x, RComplex base, BinaryMapArithmeticFunctionNode div, NAProfile naBase) { + if (naBase.isNA(base)) { + return RComplex.createNA(); + } + if (isNaN(base)) { + nanProfile.enter(); + return base; + } + return logb(x, base, div, true); + } - return Math.log(x) / Math.log(base); + private RComplex logb(RComplex x, RComplex base, BinaryMapArithmeticFunctionNode div, boolean nanWarning) { + RComplex logx = logb(x); + if (base.getRealPart() == Math.E) { + return logx; + } + + RComplex logbase = logb(base); + RComplex ret = div.applyComplex(logx, logbase); + if (nanWarning && isNaN(ret)) { + RError.warning(this, RError.Message.NAN_PRODUCED_IN_FUNCTION, "log"); + } + return ret; } - private static RDoubleVector createResult(RAbstractVector source, double[] resultData, double base, CopyOfRegAttributesNode copyAttrsNode, GetNamesAttributeNode getNamesNode, + private static RComplex logb(RComplex x) { + double re = x.getRealPart(); + double im = x.getImaginaryPart(); + + double mod = RComplex.abs(re, im); + double arg = Math.atan2(im, re); + + return RComplex.valueOf(Math.log(mod), arg); + } + + private static RDoubleVector createResult(RAbstractVector source, double[] resultData, boolean complete, CopyOfRegAttributesNode copyAttrsNode, GetNamesAttributeNode getNamesNode, GetDimAttributeNode getDimsNode) { - RDoubleVector result = RDataFactory.createDoubleVector(resultData, source.isComplete() && !RRuntime.isNA(base), getDimsNode.getDimensions(source), getNamesNode.getNames(source)); + RDoubleVector result = RDataFactory.createDoubleVector(resultData, complete, getDimsNode.getDimensions(source), getNamesNode.getNames(source)); + copyAttrsNode.execute(source, result); + return result; + } + + private static RComplexVector createResult(RAbstractVector source, double[] resultData, boolean complete, GetDimAttributeNode getDimsNode, GetNamesAttributeNode getNamesNode, + CopyOfRegAttributesNode copyAttrsNode) { + RComplexVector result = RDataFactory.createComplexVector(resultData, complete, getDimsNode.getDimensions(source), getNamesNode.getNames(source)); copyAttrsNode.execute(source, result); return result; } + + private static boolean isNaN(RComplex base) { + return Double.isNaN(base.getRealPart()) || Double.isNaN(base.getImaginaryPart()); + } } @RBuiltin(name = "log10", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ls.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ls.java index 0e05ca0385180b335d401f4dabb5fd5e165e474e..275ed1e26c715156191fea647c77b5260195d167 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ls.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ls.java @@ -23,7 +23,6 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; -import static com.oracle.truffle.r.runtime.RError.NO_CALLER; import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ARGUMENT; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -36,11 +35,11 @@ import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; @RBuiltin(name = "ls", aliases = {"objects"}, kind = INTERNAL, parameterNames = {"envir", "all.names", "sorted"}, behavior = PURE) -public abstract class Ls extends RBuiltinNode { +public abstract class Ls extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(Ls.class); - casts.arg("envir").mustBe(REnvironment.class, NO_CALLER, INVALID_ARGUMENT, "envir"); + casts.arg("envir").mustBe(REnvironment.class, INVALID_ARGUMENT, "envir"); casts.arg("all.names").asLogicalVector().findFirst().map(toBoolean()); casts.arg("sorted").asLogicalVector().findFirst().map(toBoolean()); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java index d1ac331fb5721d96bba15d982ce41211767f2174..0a382c92aa67d8b806d07d425eaf9e5e96b133a4 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java @@ -40,15 +40,15 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "make.names", kind = INTERNAL, parameterNames = {"names", "allow_"}, behavior = PURE) -public abstract class MakeNames extends RBuiltinNode { +public abstract class MakeNames extends RBuiltinNode.Arg2 { private final ConditionProfile namesLengthZero = ConditionProfile.createBinaryProfile(); private final NACheck dummyCheck = NACheck.create(); // never triggered (used for vector update) static { Casts casts = new Casts(MakeNames.class); - casts.arg("names").mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.NON_CHARACTER_NAMES); - casts.arg("allow_").defaultError(RError.SHOW_CALLER, RError.Message.INVALID_VALUE, "allow_").asLogicalVector().findFirst().mustBe(notLogicalNA()); + casts.arg("names").mustBe(stringValue(), RError.Message.NON_CHARACTER_NAMES); + casts.arg("allow_").defaultError(RError.Message.INVALID_VALUE, "allow_").asLogicalVector().findFirst().mustBe(notLogicalNA()); } @TruffleBoundary diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java index 9a0d72178e8784e0a2d6cf9ef82a6272f66e6b0a..eddadcd858b150cc4ee5544107aed1931bcb23dd 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java @@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "make.unique", kind = INTERNAL, parameterNames = {"names", "sep"}, behavior = PURE) -public abstract class MakeUnique extends RBuiltinNode { +public abstract class MakeUnique extends RBuiltinNode.Arg2 { private final ConditionProfile namesProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile duplicatesProfile = ConditionProfile.createBinaryProfile(); @@ -46,8 +46,8 @@ public abstract class MakeUnique extends RBuiltinNode { static { Casts casts = new Casts(MakeUnique.class); - casts.arg("names").defaultError(RError.SHOW_CALLER, RError.Message.NOT_CHARACTER_VECTOR, "names").mustBe(stringValue()); - casts.arg("sep").defaultError(RError.SHOW_CALLER, RError.Message.MUST_BE_STRING, "sep").mustBe(stringValue()).asStringVector().mustBe(size(1)).findFirst(); + casts.arg("names").defaultError(RError.Message.NOT_CHARACTER_VECTOR, "names").mustBe(stringValue()); + casts.arg("sep").defaultError(RError.Message.MUST_BE_STRING, "sep").mustBe(stringValue()).asStringVector().mustBe(size(1)).findFirst(); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java index f51a45e0d95e883c1f8039ad0b950dd30f8a2e07..e649410a8914d9aa6c9bffc3cd69e3e41c9960b0 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java @@ -35,25 +35,23 @@ import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.r.nodes.access.WriteVariableNode; import com.oracle.truffle.r.nodes.access.WriteVariableNode.Mode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; +import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; +import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.MapplyNodeGen.MapplyInternalNodeGen; -import com.oracle.truffle.r.nodes.builtin.base.infix.Subscript; -import com.oracle.truffle.r.nodes.builtin.base.infix.SubscriptNodeGen; import com.oracle.truffle.r.nodes.control.RLengthNode; import com.oracle.truffle.r.nodes.function.RCallNode; import com.oracle.truffle.r.nodes.function.call.RExplicitCallNode; import com.oracle.truffle.r.runtime.AnonymousFrameVariable; import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; 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.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RLogical; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @@ -64,7 +62,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; * the longest vector, with the usual recycling rule. */ @RBuiltin(name = "mapply", kind = INTERNAL, parameterNames = {"FUN", "dots", "MoreArgs"}, splitCaller = true, behavior = COMPLEX) -public abstract class Mapply extends RBuiltinNode { +public abstract class Mapply extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(Mapply.class); @@ -78,7 +76,7 @@ public abstract class Mapply extends RBuiltinNode { protected static final class ElementNode extends Node { @Child private Length lengthNode; - @Child private Subscript indexedLoadNode; + @Child private ExtractVectorNode extractNode; @Child private WriteVariableNode writeVectorElementNode; private final String vectorElementName; private final String argName; @@ -87,7 +85,7 @@ public abstract class Mapply extends RBuiltinNode { // the name is a hack to treat ReadVariableNode-s as syntax nodes this.vectorElementName = "*" + AnonymousFrameVariable.create(vectorElementName); this.lengthNode = insert(LengthNodeGen.create()); - this.indexedLoadNode = insert(SubscriptNodeGen.create()); + this.extractNode = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, false)); this.writeVectorElementNode = insert(WriteVariableNode.createAnonymous(this.vectorElementName, Mode.REGULAR, null)); this.argName = argName; } @@ -110,8 +108,6 @@ public abstract class Mapply extends RBuiltinNode { public abstract static class MapplyInternalNode extends Node implements InternalRSyntaxNodeChildren { private static final String VECTOR_ELEMENT_PREFIX = "MAPPLY_VEC_ELEM_"; - private static final RLogicalVector DROP = RDataFactory.createLogicalVectorFromScalar(true); - private static final RLogicalVector EXACT = RDataFactory.createLogicalVectorFromScalar(true); private static final ArgumentsSignature I_INDEX = ArgumentsSignature.get("i"); private static final RArgsValuesAndNames[] INDEX_CACHE = new RArgsValuesAndNames[32]; @@ -125,33 +121,8 @@ public abstract class Mapply extends RBuiltinNode { public abstract Object[] execute(VirtualFrame frame, RAbstractListVector dots, RFunction function, RAbstractListVector additionalArguments); - private static Object getVecElement(VirtualFrame frame, RAbstractListVector dots, int i, int listIndex, int[] lengths, Subscript indexedLoadNode) { - Object listElem = dots.getDataAt(listIndex); - RAbstractContainer vec = null; - if (listElem instanceof RAbstractContainer) { - vec = (RAbstractContainer) listElem; - } else { - // TODO scalar types are a nuisance! - if (listElem instanceof String) { - vec = RDataFactory.createStringVectorFromScalar((String) listElem); - } else if (listElem instanceof Integer) { - vec = RDataFactory.createIntVectorFromScalar((int) listElem); - } else if (listElem instanceof Double) { - vec = RDataFactory.createDoubleVectorFromScalar((double) listElem); - } else { - throw RInternalError.unimplemented(); - } - } - - int adjIndex = i % lengths[listIndex]; - RArgsValuesAndNames indexArg; - if (adjIndex < INDEX_CACHE.length) { - indexArg = INDEX_CACHE[adjIndex]; - } else { - indexArg = new RArgsValuesAndNames(new Object[]{adjIndex + 1}, I_INDEX); - } - return indexedLoadNode.executeBuiltin(frame, vec, indexArg, EXACT, DROP); - + private static Object getVecElement(VirtualFrame frame, RAbstractListVector dots, int i, int listIndex, int[] lengths, ExtractVectorNode extractNode) { + return extractNode.apply(frame, dots.getDataAt(listIndex), new Object[]{i % lengths[listIndex] + 1}, RLogical.TRUE, RLogical.TRUE); } @SuppressWarnings("unused") @@ -183,7 +154,7 @@ public abstract class Mapply extends RBuiltinNode { for (int i = 0; i < maxLength; i++) { /* Evaluate and store the arguments */ for (int listIndex = 0; listIndex < dotsLength; listIndex++) { - Object vecElement = getVecElement(frame, dots, i, listIndex, lengths, cachedElementNodeArray[listIndex].indexedLoadNode); + Object vecElement = getVecElement(frame, dots, i, listIndex, lengths, cachedElementNodeArray[listIndex].extractNode); cachedElementNodeArray[listIndex].writeVectorElementNode.execute(frame, vecElement); } /* Now call the function */ @@ -195,7 +166,7 @@ public abstract class Mapply extends RBuiltinNode { @Specialization(replaces = "cachedMApply") protected Object[] mApply(VirtualFrame frame, RAbstractListVector dots, RFunction function, RAbstractListVector moreArgs, @Cached("create()") RLengthNode lengthNode, - @Cached("createIndexedLoadNode()") Subscript indexedLoadNode, + @Cached("createExtractNode()") ExtractVectorNode extractNode, @Cached("create()") RExplicitCallNode callNode) { int dotsLength = dots.getLength(); int moreArgsLength = moreArgs.getLength(); @@ -226,7 +197,7 @@ public abstract class Mapply extends RBuiltinNode { for (int i = 0; i < maxLength; i++) { /* Evaluate and store the arguments */ for (int listIndex = 0; listIndex < dotsLength; listIndex++) { - Object vecElement = getVecElement(frame, dots, i, listIndex, lengths, indexedLoadNode); + Object vecElement = getVecElement(frame, dots, i, listIndex, lengths, extractNode); values[listIndex] = vecElement; } /* Now call the function */ @@ -265,8 +236,8 @@ public abstract class Mapply extends RBuiltinNode { return elementNodes; } - protected Subscript createIndexedLoadNode() { - return SubscriptNodeGen.create(); + protected ExtractVectorNode createExtractNode() { + return ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, false); } protected boolean sameNames(RAbstractListVector list, RAbstractListVector cachedList) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java index 88b10299f854ef5895632bc713867b51b4b27706..1321af4d0cebde99a813941ce1a431b947371831 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode.isMatrix; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -42,6 +43,7 @@ import com.oracle.truffle.r.nodes.binary.BinaryMapArithmeticFunctionNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RComplexVector; @@ -49,7 +51,8 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.closures.RClosures; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @@ -59,7 +62,7 @@ import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "%*%", kind = PRIMITIVE, parameterNames = {"", ""}, behavior = PURE) -public abstract class MatMult extends RBuiltinNode { +public abstract class MatMult extends RBuiltinNode.Arg2 { private static final int BLOCK_SIZE = 64; @@ -67,7 +70,6 @@ public abstract class MatMult extends RBuiltinNode { @Child private BinaryMapArithmeticFunctionNode add = new BinaryMapArithmeticFunctionNode(BinaryArithmetic.ADD.createOperation()); private final boolean promoteDimNames; - private final BranchProfile errorProfile = BranchProfile.create(); private final LoopConditionProfile mainLoopProfile = LoopConditionProfile.createCountingProfile(); private final LoopConditionProfile remainingLoopProfile = LoopConditionProfile.createCountingProfile(); @@ -80,6 +82,10 @@ public abstract class MatMult extends RBuiltinNode { @Child protected GetDimAttributeNode getBDimsNode = GetDimAttributeNode.create(); @Child protected SetDimAttributeNode setDimsNode = SetDimAttributeNode.create(); + @Child private SetDimNamesAttributeNode setDimNamesNode = SetDimNamesAttributeNode.create(); + @Child private GetDimNamesAttributeNode getADimNamesNode = GetDimNamesAttributeNode.create(); + @Child private GetDimNamesAttributeNode getBDimNamesNode = GetDimNamesAttributeNode.create(); + protected abstract Object executeObject(Object a, Object b); private final NACheck na; @@ -97,7 +103,7 @@ public abstract class MatMult extends RBuiltinNode { return MatMultNodeGen.create(true); } - @Specialization(guards = "bothZeroDim(a, b, getADimsNode, getBDimsNode)") + @Specialization(guards = "bothZeroDim(a, b)") protected RDoubleVector both0Dim(RAbstractDoubleVector a, RAbstractDoubleVector b) { int r = getBDimsNode.getDimensions(b)[1]; int c = getADimsNode.getDimensions(a)[0]; @@ -144,9 +150,8 @@ public abstract class MatMult extends RBuiltinNode { private final BranchProfile incompleteProfile = BranchProfile.create(); @CompilationFinal private boolean seenLargeMatrix; - private RDoubleVector doubleMatrixMultiply(RAbstractDoubleVector a, RAbstractDoubleVector b, int aRows, int aCols, int bRows, int bCols, SetDimNamesAttributeNode setDimNamesNode, - GetDimNamesAttributeNode getADimNamesNode, GetDimNamesAttributeNode getBDimNamesNode) { - return doubleMatrixMultiply(a, b, aRows, aCols, bRows, bCols, 1, aRows, 1, bRows, false, setDimNamesNode, getADimNamesNode, getBDimNamesNode); + private RDoubleVector doubleMatrixMultiply(RAbstractDoubleVector a, RAbstractDoubleVector b, int aRows, int aCols, int bRows, int bCols) { + return doubleMatrixMultiply(a, b, aRows, aCols, bRows, bCols, 1, aRows, 1, bRows, false); } /** @@ -167,10 +172,9 @@ public abstract class MatMult extends RBuiltinNode { * @return the result vector */ public RDoubleVector doubleMatrixMultiply(RAbstractDoubleVector a, RAbstractDoubleVector b, int aRows, int aCols, int bRows, int bCols, int aRowStride, int aColStride, int bRowStride, - int bColStride, boolean mirrored, SetDimNamesAttributeNode setDimNamesNode, GetDimNamesAttributeNode getADimNamesNode, GetDimNamesAttributeNode getBDimNamesNode) { + int bColStride, boolean mirrored) { if (aCols != bRows) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); + throw error(RError.Message.NON_CONFORMABLE_ARGS); } double[] dataA = a.materialize().getDataWithoutCopying(); double[] dataB = b.materialize().getDataWithoutCopying(); @@ -225,14 +229,15 @@ public abstract class MatMult extends RBuiltinNode { return resultVec; } - Object[] newDimsNames = new Object[2]; + Object dimName1 = RNull.instance; if (aDimNames != null && aDimNames.getLength() > 0) { - newDimsNames[0] = aDimNames.getDataAt(0); + dimName1 = aDimNames.getDataAt(0); } + Object dimName2 = RNull.instance; if (bDimNames != null && bDimNames.getLength() > 1) { - newDimsNames[1] = bDimNames.getDataAt(1); + dimName2 = bDimNames.getDataAt(1); } - setDimNamesNode.setDimNames(resultVec, RDataFactory.createList(newDimsNames)); + setDimNamesNode.setDimNames(resultVec, RDataFactory.createList(new Object[]{dimName1, dimName2})); return resultVec; } @@ -273,23 +278,33 @@ public abstract class MatMult extends RBuiltinNode { } } - @Specialization + @Specialization(guards = {"a.getClass() == aClass", "b.getClass() == bClass"}) + protected RDoubleVector multiplyDouble(RAbstractDoubleVector a, RAbstractDoubleVector b, + @Cached("a.getClass()") Class<? extends RAbstractDoubleVector> aClass, + @Cached("b.getClass()") Class<? extends RAbstractDoubleVector> bClass, + @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, + @Cached("createBinaryProfile()") ConditionProfile bIsMatrix, + @Cached("createBinaryProfile()") ConditionProfile lengthEquals) { + return doubleMultiply(aClass.cast(a), bClass.cast(b), aIsMatrix, bIsMatrix, lengthEquals); + } + + @Specialization(replaces = "multiplyDouble") protected RDoubleVector multiply(RAbstractDoubleVector a, RAbstractDoubleVector b, @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, @Cached("createBinaryProfile()") ConditionProfile bIsMatrix, - @Cached("createBinaryProfile()") ConditionProfile lengthEquals, - @Cached("create()") SetDimNamesAttributeNode setDimNamesNode, - @Cached("create()") GetDimNamesAttributeNode getADimNamesNode, - @Cached("create()") GetDimNamesAttributeNode getBDimNamesNode) { - if (aIsMatrix.profile(a.isMatrix())) { - if (bIsMatrix.profile(b.isMatrix())) { - int[] aDimensions = getADimsNode.getDimensions(a); - int[] bDimensions = getBDimsNode.getDimensions(b); - return doubleMatrixMultiply(a, b, aDimensions[0], aDimensions[1], bDimensions[0], bDimensions[1], setDimNamesNode, getADimNamesNode, getBDimNamesNode); + @Cached("createBinaryProfile()") ConditionProfile lengthEquals) { + return doubleMultiply(a, b, aIsMatrix, bIsMatrix, lengthEquals); + } + + private RDoubleVector doubleMultiply(RAbstractDoubleVector a, RAbstractDoubleVector b, ConditionProfile aIsMatrix, ConditionProfile bIsMatrix, ConditionProfile lengthEquals) { + int[] aDimensions = getADimsNode.getDimensions(a); + int[] bDimensions = getBDimsNode.getDimensions(b); + if (aIsMatrix.profile(isMatrix(aDimensions))) { + if (bIsMatrix.profile(isMatrix(bDimensions))) { + return doubleMatrixMultiply(a, b, aDimensions[0], aDimensions[1], bDimensions[0], bDimensions[1]); } else { - int[] aDim = getADimsNode.getDimensions(a); - int aRows = aDim[0]; - int aCols = aDim[1]; + int aRows = aDimensions[0]; + int aCols = aDimensions[1]; int bRows; int bCols; if (lengthEquals.profile(aCols == b.getLength())) { @@ -299,13 +314,12 @@ public abstract class MatMult extends RBuiltinNode { bRows = 1; bCols = b.getLength(); } - return doubleMatrixMultiply(a, b, aRows, aCols, bRows, bCols, setDimNamesNode, getADimNamesNode, getBDimNamesNode); + return doubleMatrixMultiply(a, b, aRows, aCols, bRows, bCols); } } else { - if (bIsMatrix.profile(b.isMatrix())) { - int[] bDim = getBDimsNode.getDimensions(b); - int bRows = bDim[0]; - int bCols = bDim[1]; + if (bIsMatrix.profile(isMatrix(bDimensions))) { + int bRows = bDimensions[0]; + int bCols = bDimensions[1]; int aRows; int aCols; if (lengthEquals.profile(bRows == a.getLength())) { @@ -315,11 +329,10 @@ public abstract class MatMult extends RBuiltinNode { aRows = a.getLength(); aCols = 1; } - return doubleMatrixMultiply(a, b, aRows, aCols, bRows, bCols, setDimNamesNode, getADimNamesNode, getBDimNamesNode); + return doubleMatrixMultiply(a, b, aRows, aCols, bRows, bCols); } else { if (a.getLength() != b.getLength()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); + throw error(RError.Message.NON_CONFORMABLE_ARGS); } double result = 0.0; na.enable(a); @@ -339,22 +352,34 @@ public abstract class MatMult extends RBuiltinNode { // complex-complex - @Specialization + @Specialization(guards = {"a.getClass() == aClass", "b.getClass() == bClass"}) + protected RComplexVector multiplyComplex(RAbstractComplexVector a, RAbstractComplexVector b, + @Cached("a.getClass()") Class<? extends RAbstractComplexVector> aClass, + @Cached("b.getClass()") Class<? extends RAbstractComplexVector> bClass, + @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, + @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) { + return complexMultiply(aClass.cast(a), bClass.cast(b), aIsMatrix, bIsMatrix); + } + + @Specialization(replaces = "multiplyComplex") protected RComplexVector multiply(RAbstractComplexVector a, RAbstractComplexVector b, @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) { - if (aIsMatrix.profile(a.isMatrix())) { - if (bIsMatrix.profile(b.isMatrix())) { - int[] aDim = getADimsNode.getDimensions(a); - int[] bDim = getBDimsNode.getDimensions(b); - final int aCols = aDim[1]; - final int bRows = bDim[0]; + return complexMultiply(a, b, aIsMatrix, bIsMatrix); + } + + private RComplexVector complexMultiply(RAbstractComplexVector a, RAbstractComplexVector b, ConditionProfile aIsMatrix, ConditionProfile bIsMatrix) { + int[] aDimensions = getADimsNode.getDimensions(a); + int[] bDimensions = getBDimsNode.getDimensions(b); + if (aIsMatrix.profile(isMatrix(aDimensions))) { + if (bIsMatrix.profile(isMatrix(bDimensions))) { + final int aCols = aDimensions[1]; + final int bRows = bDimensions[0]; if (aCols != bRows) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); + throw error(RError.Message.NON_CONFORMABLE_ARGS); } - final int aRows = aDim[0]; - final int bCols = bDim[1]; + final int aRows = aDimensions[0]; + final int bCols = bDimensions[1]; double[] result = new double[(aRows * bCols) << 1]; na.enable(a); na.enable(b); @@ -372,12 +397,10 @@ public abstract class MatMult extends RBuiltinNode { } return RDataFactory.createComplexVector(result, na.neverSeenNA(), new int[]{aRows, bCols}); } else { - int[] aDim = getADimsNode.getDimensions(a); - final int aCols = aDim[1]; - final int aRows = aDim[0]; + final int aCols = aDimensions[1]; + final int aRows = aDimensions[0]; if (aCols != 1 && aCols != b.getLength()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); + throw error(RError.Message.NON_CONFORMABLE_ARGS); } na.enable(a); na.enable(b); @@ -407,13 +430,11 @@ public abstract class MatMult extends RBuiltinNode { } } } else { - if (bIsMatrix.profile(b.isMatrix())) { - int[] bDim = getBDimsNode.getDimensions(b); - final int bRows = bDim[0]; - final int bCols = bDim[1]; + if (bIsMatrix.profile(isMatrix(bDimensions))) { + final int bRows = bDimensions[0]; + final int bCols = bDimensions[1]; if (bRows != 1 && bRows != a.getLength()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); + throw error(RError.Message.NON_CONFORMABLE_ARGS); } na.enable(a); na.enable(b); @@ -443,8 +464,7 @@ public abstract class MatMult extends RBuiltinNode { } } else { if (a.getLength() != b.getLength()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); + throw error(RError.Message.NON_CONFORMABLE_ARGS); } RComplex result = RDataFactory.createComplexZero(); na.enable(a); @@ -460,22 +480,34 @@ public abstract class MatMult extends RBuiltinNode { // int-int - @Specialization + @Specialization(guards = {"a.getClass() == aClass", "b.getClass() == bClass"}) + protected RIntVector multiplyInt(RAbstractIntVector a, RAbstractIntVector b, + @Cached("a.getClass()") Class<? extends RAbstractIntVector> aClass, + @Cached("b.getClass()") Class<? extends RAbstractIntVector> bClass, + @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, + @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) { + return intMultiply(aClass.cast(a), bClass.cast(b), aIsMatrix, bIsMatrix); + } + + @Specialization(replaces = "multiplyInt") protected RIntVector multiply(RAbstractIntVector a, RAbstractIntVector b, @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) { - if (aIsMatrix.profile(a.isMatrix())) { - if (bIsMatrix.profile(b.isMatrix())) { - int[] aDim = getADimsNode.getDimensions(a); - int[] bDim = getBDimsNode.getDimensions(b); - final int aCols = aDim[1]; - final int bRows = bDim[0]; + return intMultiply(a, b, aIsMatrix, bIsMatrix); + } + + private RIntVector intMultiply(RAbstractIntVector a, RAbstractIntVector b, ConditionProfile aIsMatrix, ConditionProfile bIsMatrix) { + int[] aDimensions = getADimsNode.getDimensions(a); + int[] bDimensions = getBDimsNode.getDimensions(b); + if (aIsMatrix.profile(isMatrix(aDimensions))) { + if (bIsMatrix.profile(isMatrix(bDimensions))) { + int aCols = aDimensions[1]; + int bRows = bDimensions[0]; if (aCols != bRows) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); + throw error(RError.Message.NON_CONFORMABLE_ARGS); } - final int aRows = aDim[0]; - final int bCols = bDim[1]; + int aRows = aDimensions[0]; + int bCols = bDimensions[1]; int[] result = new int[aRows * bCols]; na.enable(a); na.enable(b); @@ -491,12 +523,10 @@ public abstract class MatMult extends RBuiltinNode { } return RDataFactory.createIntVector(result, na.neverSeenNA(), new int[]{aRows, bCols}); } else { - int[] aDim = getADimsNode.getDimensions(a); - final int aCols = aDim[1]; - final int aRows = aDim[0]; + final int aCols = aDimensions[1]; + final int aRows = aDimensions[0]; if (aCols != 1 && aCols != b.getLength()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); + throw error(RError.Message.NON_CONFORMABLE_ARGS); } na.enable(a); na.enable(b); @@ -524,13 +554,11 @@ public abstract class MatMult extends RBuiltinNode { } } } else { - int[] bDim = getBDimsNode.getDimensions(b); - if (bIsMatrix.profile(b.isMatrix())) { - final int bCols = bDim[1]; - final int bRows = bDim[0]; + if (bIsMatrix.profile(isMatrix(bDimensions))) { + final int bCols = bDimensions[1]; + final int bRows = bDimensions[0]; if (bRows != 1 && bRows != a.getLength()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); + throw error(RError.Message.NON_CONFORMABLE_ARGS); } na.enable(a); na.enable(b); @@ -558,8 +586,7 @@ public abstract class MatMult extends RBuiltinNode { } } else { if (a.getLength() != b.getLength()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS); + throw error(RError.Message.NON_CONFORMABLE_ARGS); } int result = 0; na.enable(result); @@ -576,115 +603,66 @@ public abstract class MatMult extends RBuiltinNode { @Specialization protected RIntVector multiply(RAbstractLogicalVector aOriginal, RAbstractLogicalVector bOriginal, + @Cached("createBinaryProfile()") ConditionProfile isNAProfile, @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) { - return multiply(RClosures.createLogicalToIntVector(aOriginal), RClosures.createLogicalToIntVector(bOriginal), aIsMatrix, bIsMatrix); + return intMultiply((RAbstractIntVector) aOriginal.castSafe(RType.Integer, isNAProfile), (RAbstractIntVector) bOriginal.castSafe(RType.Integer, isNAProfile), aIsMatrix, bIsMatrix); } // to int @Specialization - protected RIntVector multiply(RAbstractLogicalVector a, RAbstractIntVector b, + protected RIntVector multiply(RAbstractLogicalVector aOriginal, RAbstractIntVector b, + @Cached("createBinaryProfile()") ConditionProfile isNAProfile, @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) { - return multiply(RClosures.createLogicalToIntVector(a), b, aIsMatrix, bIsMatrix); + return intMultiply((RAbstractIntVector) aOriginal.castSafe(RType.Integer, isNAProfile), b, aIsMatrix, bIsMatrix); } @Specialization - protected RIntVector multiply(RAbstractIntVector a, RAbstractLogicalVector b, + protected RIntVector multiply(RAbstractIntVector a, RAbstractLogicalVector bOriginal, + @Cached("createBinaryProfile()") ConditionProfile isNAProfile, @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) { - return multiply(a, RClosures.createLogicalToIntVector(b), aIsMatrix, bIsMatrix); - } - - // to complex - - @Specialization - protected RComplexVector multiply(RAbstractIntVector a, RAbstractComplexVector b, - @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, - @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) { - return multiply(RClosures.createIntToComplexVector(a), b, aIsMatrix, bIsMatrix); - } - - @Specialization - protected RComplexVector multiply(RAbstractComplexVector a, RAbstractIntVector b, - @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, - @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) { - return multiply(a, RClosures.createIntToComplexVector(b), aIsMatrix, bIsMatrix); - } - - @Specialization - protected RComplexVector multiply(RAbstractLogicalVector a, RAbstractComplexVector b, - @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, - @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) { - return multiply(RClosures.createLogicalToComplexVector(a), b, aIsMatrix, bIsMatrix); - } - - @Specialization - protected RComplexVector multiply(RAbstractComplexVector a, RAbstractLogicalVector b, - @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, - @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) { - return multiply(a, RClosures.createLogicalToComplexVector(b), aIsMatrix, bIsMatrix); - } - - @Specialization - protected RComplexVector multiply(RAbstractDoubleVector a, RAbstractComplexVector b, - @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, - @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) { - return multiply(RClosures.createDoubleToComplexVector(a), b, aIsMatrix, bIsMatrix); - } - - @Specialization - protected RComplexVector multiply(RAbstractComplexVector a, RAbstractDoubleVector b, - @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, - @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) { - return multiply(a, RClosures.createDoubleToComplexVector(b), aIsMatrix, bIsMatrix); + return intMultiply(a, (RAbstractIntVector) bOriginal.castSafe(RType.Integer, isNAProfile), aIsMatrix, bIsMatrix); } // to double - @Specialization - protected RDoubleVector multiply(RAbstractIntVector a, RAbstractDoubleVector b, + @Specialization(guards = {"!isRAbstractComplexVector(a)"}) + protected RDoubleVector multiply(RAbstractAtomicVector a, RAbstractDoubleVector b, @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, @Cached("createBinaryProfile()") ConditionProfile bIsMatrix, @Cached("createBinaryProfile()") ConditionProfile lengthEquals, - @Cached("create()") SetDimNamesAttributeNode setDimNamesNode, - @Cached("create()") GetDimNamesAttributeNode getADimNamesNode, - @Cached("create()") GetDimNamesAttributeNode getBDimNamesNode) { - return multiply(RClosures.createIntToDoubleVector(a), b, aIsMatrix, bIsMatrix, lengthEquals, setDimNamesNode, getADimNamesNode, getBDimNamesNode); + @Cached("createBinaryProfile()") ConditionProfile isNAProfile) { + return doubleMultiply((RAbstractDoubleVector) a.castSafe(RType.Double, isNAProfile), b, aIsMatrix, bIsMatrix, lengthEquals); } - @Specialization - protected RDoubleVector multiply(RAbstractDoubleVector a, RAbstractIntVector b, + @Specialization(guards = {"!isRAbstractComplexVector(b)"}) + protected RDoubleVector multiply(RAbstractDoubleVector a, RAbstractAtomicVector b, @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, @Cached("createBinaryProfile()") ConditionProfile bIsMatrix, @Cached("createBinaryProfile()") ConditionProfile lengthEquals, - @Cached("create()") SetDimNamesAttributeNode setDimNamesNode, - @Cached("create()") GetDimNamesAttributeNode getADimNamesNode, - @Cached("create()") GetDimNamesAttributeNode getBDimNamesNode) { - return multiply(a, RClosures.createIntToDoubleVector(b), aIsMatrix, bIsMatrix, lengthEquals, setDimNamesNode, getADimNamesNode, getBDimNamesNode); + @Cached("createBinaryProfile()") ConditionProfile isNAProfile) { + return doubleMultiply(a, (RAbstractDoubleVector) b.castSafe(RType.Double, isNAProfile), aIsMatrix, bIsMatrix, lengthEquals); } + // to complex + @Specialization - protected RDoubleVector multiply(RAbstractLogicalVector a, RAbstractDoubleVector b, + protected RComplexVector multiply(RAbstractAtomicVector a, RAbstractComplexVector b, @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, @Cached("createBinaryProfile()") ConditionProfile bIsMatrix, - @Cached("createBinaryProfile()") ConditionProfile lengthEquals, - @Cached("create()") SetDimNamesAttributeNode setDimNamesNode, - @Cached("create()") GetDimNamesAttributeNode getADimNamesNode, - @Cached("create()") GetDimNamesAttributeNode getBDimNamesNode) { - return multiply(RClosures.createLogicalToDoubleVector(a), b, aIsMatrix, bIsMatrix, lengthEquals, setDimNamesNode, getADimNamesNode, getBDimNamesNode); + @Cached("createBinaryProfile()") ConditionProfile isNAProfile) { + return complexMultiply((RAbstractComplexVector) a.castSafe(RType.Complex, isNAProfile), b, aIsMatrix, bIsMatrix); } @Specialization - protected RDoubleVector multiply(RAbstractDoubleVector a, RAbstractLogicalVector b, + protected RComplexVector multiply(RAbstractComplexVector a, RAbstractAtomicVector b, @Cached("createBinaryProfile()") ConditionProfile aIsMatrix, @Cached("createBinaryProfile()") ConditionProfile bIsMatrix, - @Cached("createBinaryProfile()") ConditionProfile lengthEquals, - @Cached("create()") SetDimNamesAttributeNode setDimNamesNode, - @Cached("create()") GetDimNamesAttributeNode getADimNamesNode, - @Cached("create()") GetDimNamesAttributeNode getBDimNamesNode) { - return multiply(a, RClosures.createLogicalToDoubleVector(b), aIsMatrix, bIsMatrix, lengthEquals, setDimNamesNode, getADimNamesNode, getBDimNamesNode); + @Cached("createBinaryProfile()") ConditionProfile isNAProfile) { + return complexMultiply(a, (RAbstractComplexVector) b.castSafe(RType.Complex, isNAProfile), aIsMatrix, bIsMatrix); } // errors @@ -692,16 +670,16 @@ public abstract class MatMult extends RBuiltinNode { @Fallback @TruffleBoundary protected RDoubleVector doRaw(@SuppressWarnings("unused") Object a, @SuppressWarnings("unused") Object b) { - throw RError.error(this, RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR); + throw error(RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR); } // guards - protected static boolean bothZeroDim(RAbstractVector a, RAbstractVector b, GetDimAttributeNode getADimsNode, GetDimAttributeNode getBDimsNode) { + protected boolean bothZeroDim(RAbstractVector a, RAbstractVector b) { return hasZeroDim(a, getADimsNode) && hasZeroDim(b, getBDimsNode); } - protected static boolean hasZeroDim(RAbstractVector v, GetDimAttributeNode getDimsNode) { + protected boolean hasZeroDim(RAbstractVector v, GetDimAttributeNode getDimsNode) { int[] dims = getDimsNode.getDimensions(v); if (dims == null || dims.length == 0) { return false; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java index 291aad6c297e6276d231df73417c2083fb91badd..610db0cda98c35e1f3346426904cfd96c4918104 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java @@ -22,6 +22,8 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalFalse; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; import static com.oracle.truffle.r.runtime.RError.Message.MATCH_VECTOR_ARGS; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -30,20 +32,24 @@ import java.util.Arrays; import com.oracle.truffle.api.CompilerDirectives; 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.nodes.Node; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.base.MatchNodeGen.MatchInternalNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.MatchNodeGen.ProfiledMatchInternalNodeGen; import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode; import com.oracle.truffle.r.nodes.helpers.RFactorNodes; import com.oracle.truffle.r.nodes.unary.CastStringNode; import com.oracle.truffle.r.nodes.unary.CastStringNodeGen; -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.RType; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.closures.RClosures; @@ -55,13 +61,14 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -import com.oracle.truffle.r.runtime.ops.na.NACheck; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.ops.na.NAProfile; +/* + * TODO: handle "incomparables" parameter. + */ @RBuiltin(name = "match", kind = INTERNAL, parameterNames = {"x", "table", "nomatch", "incomparables"}, behavior = PURE) -public abstract class Match extends RBuiltinNode { - - private static final int TABLE_SIZE_FACTOR = 10; +public abstract class Match extends RBuiltinNode.Arg4 { protected abstract Object executeRIntVector(Object x, Object table, Object noMatch, Object incomparables); @@ -69,9 +76,6 @@ public abstract class Match extends RBuiltinNode { @Child private Match matchRecursive; - private final NACheck naCheck = NACheck.create(); - private final ConditionProfile bigTableProfile = ConditionProfile.createBinaryProfile(); - static { Casts casts = new Casts(Match.class); // TODO initially commented out because of use of scalars, the commented out version @@ -81,27 +85,14 @@ public abstract class Match extends RBuiltinNode { // MATCH_VECTOR_ARGS).asVectorPreserveAttrs(true); // casts.arg("table").allowNull().mustBe(abstractVectorValue()).asVectorPreserveAttrs(true); casts.arg("nomatch").asIntegerVector().findFirst(); - // casts.arg("incomparables").allowNull().mustBe(abstractVectorValue()).asVectorPreserveAttrs(true); + casts.arg("incomparables").defaultError(Message.GENERIC, "usage of 'incomparables' in match not implemented").allowNull().mustBe(logicalValue()).asLogicalVector().findFirst().mustBe( + logicalFalse()); } - private RAbstractStringVector castString(RAbstractVector operand) { - if (castString == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castString = insert(CastStringNodeGen.create(false, false, false)); - } - return (RAbstractStringVector) castString.execute(operand); - } - - private Object matchRecursive(Object x, Object table, Object noMatch, Object incomparables) { - if (matchRecursive == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - matchRecursive = insert(MatchNodeGen.create()); - } - return matchRecursive.executeRIntVector(x, table, noMatch, incomparables); + protected static ProfiledMatchInternalNode createInternal() { + return ProfiledMatchInternalNodeGen.create(); } - // FIXME deal incomparables parameter - @Specialization @SuppressWarnings("unused") protected RIntVector match(RNull x, RNull table, int nomatch, Object incomparables) { @@ -116,752 +107,790 @@ public abstract class Match extends RBuiltinNode { @Specialization @SuppressWarnings("unused") - protected RIntVector match(RAbstractVector x, RNull table, int nomatch, Object incomparables) { + protected RIntVector match(RAbstractVector x, RNull table, int nomatch, Object incomparables, + @Cached("createBinaryProfile()") ConditionProfile na) { int[] data = new int[x.getLength()]; Arrays.fill(data, nomatch); - naCheck.enable(nomatch); - naCheck.check(nomatch); - return RDataFactory.createIntVector(data, naCheck.neverSeenNA()); + return RDataFactory.createIntVector(data, na.profile(!RRuntime.isNA(nomatch))); + } + + @Child private InheritsCheckNode factorInheritsCheck = new InheritsCheckNode(RRuntime.CLASS_FACTOR); + + protected boolean isFactor(Object o) { + return factorInheritsCheck.execute(o); } @Specialization(guards = {"isFactor(x)", "isFactor(table)"}) - protected Object matchFactor(RAbstractIntVector x, RAbstractIntVector table, int nomatch, Object incomparables, - @Cached("create()") RFactorNodes.GetLevels getLevelsNode) { - naCheck.enable(x); - naCheck.enable(table); - return matchRecursive(RClosures.createFactorToVector(x, true, getLevelsNode.execute(x)), - RClosures.createFactorToVector(table, true, getLevelsNode.execute(table)), nomatch, incomparables); + protected Object matchFactor(RAbstractIntVector x, RAbstractIntVector table, int nomatch, @SuppressWarnings("unused") Object incomparables, + @Cached("create()") RFactorNodes.GetLevels getLevelsNode, + @Cached("createInternal()") ProfiledMatchInternalNode match) { + return match.execute(RClosures.createFactorToVector(x, true, getLevelsNode.execute(x)), + RClosures.createFactorToVector(table, true, getLevelsNode.execute(table)), nomatch); } @Specialization(guards = {"isFactor(x)", "!isFactor(table)"}) - protected Object matchFactor(RAbstractIntVector x, RAbstractVector table, int nomatch, Object incomparables, - @Cached("create()") RFactorNodes.GetLevels getLevelsNode) { - naCheck.enable(x); - return matchRecursive(RClosures.createFactorToVector(x, true, getLevelsNode.execute(x)), table, nomatch, incomparables); + protected Object matchFactor(RAbstractIntVector x, RAbstractVector table, int nomatch, @SuppressWarnings("unused") Object incomparables, + @Cached("create()") RFactorNodes.GetLevels getLevelsNode, + @Cached("createInternal()") ProfiledMatchInternalNode match) { + return match.execute(RClosures.createFactorToVector(x, true, getLevelsNode.execute(x)), table, nomatch); } @Specialization(guards = {"!isFactor(x)", "isFactor(table)"}) - protected Object matchFactor(RAbstractVector x, RAbstractIntVector table, int nomatch, Object incomparables, - @Cached("create()") RFactorNodes.GetLevels getLevelsNode) { - naCheck.enable(table); - return matchRecursive(x, RClosures.createFactorToVector(table, true, getLevelsNode.execute(table)), nomatch, incomparables); + protected Object matchFactor(RAbstractVector x, RAbstractIntVector table, int nomatch, @SuppressWarnings("unused") Object incomparables, + @Cached("create()") RFactorNodes.GetLevels getLevelsNode, + @Cached("createInternal()") ProfiledMatchInternalNode match) { + return match.execute(x, RClosures.createFactorToVector(table, true, getLevelsNode.execute(table)), nomatch); } - @Specialization - protected Object matchList(RAbstractListVector x, Object table, Object nomatchObj, Object incomparables, - @Cached("create()") CastStringNode cast) { - return matchRecursive(cast.execute(x), table, nomatchObj, incomparables); + @Specialization(guards = {"!isRAbstractIntVector(table) || !isFactor(table)"}) + protected Object matchList(RAbstractListVector x, RAbstractVector table, int nomatchObj, @SuppressWarnings("unused") Object incomparables, + @Cached("create()") CastStringNode cast, + @Cached("createInternal()") ProfiledMatchInternalNode match) { + return match.execute((RAbstractVector) cast.doCast(x), table, nomatchObj); } - @Specialization - protected RIntVector match(RAbstractIntVector x, RAbstractIntVector table, int nomatch, @SuppressWarnings("unused") Object incomparables) { - int[] result = initResult(x.getLength(), nomatch); - boolean matchAll = true; - NonRecursiveHashMapInt hashTable; - if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) { - hashTable = new NonRecursiveHashMapInt(x.getLength()); - NonRecursiveHashSetInt hashSet = new NonRecursiveHashSetInt(x.getLength()); - for (int i = 0; i < result.length; i++) { - hashSet.add(x.getDataAt(i)); - } - for (int i = table.getLength() - 1; i >= 0; i--) { - int val = table.getDataAt(i); - if (hashSet.contains(val)) { - hashTable.put(val, i); - } - } - } else { - hashTable = new NonRecursiveHashMapInt(table.getLength()); - for (int i = table.getLength() - 1; i >= 0; i--) { - hashTable.put(table.getDataAt(i), i); - } - } - for (int i = 0; i < result.length; i++) { - int xx = x.getDataAt(i); - int index = hashTable.get(xx); - if (index != -1) { - result[i] = index + 1; - } else { - matchAll = false; - } - } - return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch)); + @Specialization(guards = {"!isRAbstractListVector(x)", "!isRAbstractIntVector(x) || !isFactor(x)", "!isRAbstractIntVector(table) || !isFactor(table)"}) + protected Object match(RAbstractVector x, RAbstractVector table, int noMatch, @SuppressWarnings("unused") Object incomparables, + @Cached("createInternal()") ProfiledMatchInternalNode match) { + return match.execute(x, table, noMatch); } - @Specialization - protected RIntVector match(RAbstractDoubleVector x, RAbstractIntVector table, int nomatch, @SuppressWarnings("unused") Object incomparables) { - int[] result = initResult(x.getLength(), nomatch); - boolean matchAll = true; - NonRecursiveHashMapDouble hashTable; - if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) { - hashTable = new NonRecursiveHashMapDouble(x.getLength()); - NonRecursiveHashSetDouble hashSet = new NonRecursiveHashSetDouble(x.getLength()); - for (int i = 0; i < result.length; i++) { - hashSet.add(x.getDataAt(i)); - } - for (int i = table.getLength() - 1; i >= 0; i--) { - int val = table.getDataAt(i); - if (hashSet.contains(RRuntime.int2double(val))) { - hashTable.put(RRuntime.int2double(val), i); - } - } - } else { - hashTable = new NonRecursiveHashMapDouble(table.getLength()); - for (int i = table.getLength() - 1; i >= 0; i--) { - hashTable.put(RRuntime.int2double(table.getDataAt(i)), i); - } + @Fallback + @SuppressWarnings("unused") + protected RIntVector match(Object x, Object table, Object nomatch, Object incomparables) { + throw error(MATCH_VECTOR_ARGS); + } + + protected abstract static class ProfiledMatchInternalNode extends Node { + + protected static final int PROFILE_LIMIT = 2; + + protected abstract Object execute(RAbstractVector x, RAbstractVector table, int noMatch); + + protected static MatchInternalNode createInternal() { + return MatchInternalNodeGen.create(); } - for (int i = 0; i < result.length; i++) { - double xx = x.getDataAt(i); - int index = hashTable.get(xx); - if (index != -1) { - result[i] = index + 1; - } else { - matchAll = false; - } + + @Specialization(limit = "PROFILE_LIMIT", guards = {"x.getClass() == xClass", "table.getClass() == tableClass"}) + protected static Object matchProfiled(RAbstractVector x, RAbstractVector table, int noMatch, + @Cached("x.getClass()") Class<? extends RAbstractVector> xClass, + @Cached("table.getClass()") Class<? extends RAbstractVector> tableClass, + @Cached("createInternal()") MatchInternalNode match) { + return match.execute(xClass.cast(x), tableClass.cast(table), noMatch); + } + + @Specialization(replaces = "matchProfiled") + protected static Object match(RAbstractVector x, RAbstractVector table, int noMatch, + @Cached("createInternal()") MatchInternalNode match) { + return match.execute(x, table, noMatch); } - return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch)); } - @Specialization - protected RIntVector match(RAbstractIntVector x, RAbstractDoubleVector table, int nomatch, @SuppressWarnings("unused") Object incomparables) { - int[] result = initResult(x.getLength(), nomatch); - boolean matchAll = true; - NonRecursiveHashMapInt hashTable; - if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) { - hashTable = new NonRecursiveHashMapInt(x.getLength()); - NonRecursiveHashSetInt hashSet = new NonRecursiveHashSetInt(x.getLength()); - for (int i = 0; i < result.length; i++) { - hashSet.add(x.getDataAt(i)); + protected abstract static class MatchInternalNode extends RBaseNode { + + private static final int TABLE_SIZE_FACTOR = 10; + + protected abstract Object execute(RAbstractVector x, RAbstractVector table, int noMatch); + + @Child private CastStringNode castString; + + @Child private MatchInternalNode matchRecursive; + + private final ConditionProfile bigTableProfile = ConditionProfile.createBinaryProfile(); + + private RAbstractStringVector castString(RAbstractVector operand) { + if (castString == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + castString = insert(CastStringNodeGen.create(false, false, false)); } - for (int i = table.getLength() - 1; i >= 0; i--) { - double val = table.getDataAt(i); - if (RRuntime.isNA(val) && hashSet.contains(RRuntime.INT_NA)) { - hashTable.put(RRuntime.INT_NA, i); - } else if (val == (int) val && hashSet.contains((int) val)) { - hashTable.put((int) val, i); + return (RAbstractStringVector) castString.doCast(operand); + } + + @Specialization + protected RIntVector match(RAbstractIntVector x, RAbstractIntVector table, int nomatch) { + int[] result = initResult(x.getLength(), nomatch); + boolean matchAll = true; + NonRecursiveHashMapInt hashTable; + if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) { + hashTable = new NonRecursiveHashMapInt(x.getLength()); + NonRecursiveHashSetInt hashSet = new NonRecursiveHashSetInt(x.getLength()); + for (int i = 0; i < result.length; i++) { + hashSet.add(x.getDataAt(i)); } - } - } else { - hashTable = new NonRecursiveHashMapInt(table.getLength()); - for (int i = table.getLength() - 1; i >= 0; i--) { - double xx = table.getDataAt(i); - if (RRuntime.isNA(xx)) { - hashTable.put(RRuntime.INT_NA, i); - } else if (xx == (int) xx) { - hashTable.put((int) xx, i); + for (int i = table.getLength() - 1; i >= 0; i--) { + int val = table.getDataAt(i); + if (hashSet.contains(val)) { + hashTable.put(val, i); + } } - } - } - for (int i = 0; i < result.length; i++) { - int xx = x.getDataAt(i); - int index = hashTable.get(xx); - if (index != -1) { - result[i] = index + 1; } else { - matchAll = false; + hashTable = new NonRecursiveHashMapInt(table.getLength()); + for (int i = table.getLength() - 1; i >= 0; i--) { + hashTable.put(table.getDataAt(i), i); + } } - } - return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch)); - } - - @Specialization - protected RIntVector match(RAbstractDoubleVector x, RAbstractDoubleVector table, int nomatch, @SuppressWarnings("unused") Object incomparables) { - int[] result = initResult(x.getLength(), nomatch); - boolean matchAll = true; - NonRecursiveHashMapDouble hashTable; - if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) { - hashTable = new NonRecursiveHashMapDouble(x.getLength()); - NonRecursiveHashSetDouble hashSet = new NonRecursiveHashSetDouble(x.getLength()); for (int i = 0; i < result.length; i++) { - hashSet.add(x.getDataAt(i)); - } - for (int i = table.getLength() - 1; i >= 0; i--) { - double val = table.getDataAt(i); - if (hashSet.contains(val)) { - hashTable.put(val, i); + int xx = x.getDataAt(i); + int index = hashTable.get(xx); + if (index != -1) { + result[i] = index + 1; + } else { + matchAll = false; } } - } else { - hashTable = new NonRecursiveHashMapDouble(table.getLength()); - for (int i = table.getLength() - 1; i >= 0; i--) { - hashTable.put(table.getDataAt(i), i); - } + return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch)); } - for (int i = 0; i < result.length; i++) { - double xx = x.getDataAt(i); - int index = hashTable.get(xx); - if (index != -1) { - result[i] = index + 1; + + @Specialization + protected RIntVector match(RAbstractDoubleVector x, RAbstractIntVector table, int nomatch) { + int[] result = initResult(x.getLength(), nomatch); + boolean matchAll = true; + NonRecursiveHashMapDouble hashTable; + if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) { + hashTable = new NonRecursiveHashMapDouble(x.getLength()); + NonRecursiveHashSetDouble hashSet = new NonRecursiveHashSetDouble(x.getLength()); + for (int i = 0; i < result.length; i++) { + hashSet.add(x.getDataAt(i)); + } + for (int i = table.getLength() - 1; i >= 0; i--) { + int val = table.getDataAt(i); + if (hashSet.contains(RRuntime.int2double(val))) { + hashTable.put(RRuntime.int2double(val), i); + } + } } else { - matchAll = false; + hashTable = new NonRecursiveHashMapDouble(table.getLength()); + for (int i = table.getLength() - 1; i >= 0; i--) { + hashTable.put(RRuntime.int2double(table.getDataAt(i)), i); + } } - } - return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch)); - } - - @Specialization - protected RIntVector match(RAbstractIntVector x, RAbstractLogicalVector table, int nomatch, @SuppressWarnings("unused") Object incomparables) { - int[] result = initResult(x.getLength(), nomatch); - boolean matchAll = true; - int[] values = {RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA}; - int[] indexes = new int[values.length]; - for (int i = 0; i < values.length; i++) { - byte value = (byte) values[i]; - for (int j = 0; j < table.getLength(); j++) { - if (table.getDataAt(j) == value) { - indexes[i] = j + 1; - break; - } - } - values[i] = RRuntime.logical2int(value); - } - for (int i = 0; i < result.length; i++) { - int xx = x.getDataAt(i); - boolean match = false; - for (int j = 0; j < values.length; j++) { - if (xx == values[j] && indexes[j] != 0) { - result[i] = indexes[j]; - match = true; - break; + for (int i = 0; i < result.length; i++) { + double xx = x.getDataAt(i); + int index = hashTable.get(xx); + if (index != -1) { + result[i] = index + 1; + } else { + matchAll = false; } } - matchAll &= match; + return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch)); } - return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch)); - } - @Specialization(guards = "x.getLength() == 1") - protected int matchSizeOne(RAbstractStringVector x, RAbstractStringVector table, int nomatch, @SuppressWarnings("unused") Object incomparables, - @Cached("create()") NAProfile naProfile, - @Cached("create()") BranchProfile foundProfile, - @Cached("create()") BranchProfile notFoundProfile) { - String element = x.getDataAt(0); - int length = table.getLength(); - if (naProfile.isNA(element)) { - for (int i = 0; i < length; i++) { - if (RRuntime.isNA(table.getDataAt(i))) { - foundProfile.enter(); - return i + 1; + @Specialization + protected RIntVector match(RAbstractIntVector x, RAbstractDoubleVector table, int nomatch) { + int[] result = initResult(x.getLength(), nomatch); + boolean matchAll = true; + NonRecursiveHashMapInt hashTable; + if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) { + hashTable = new NonRecursiveHashMapInt(x.getLength()); + NonRecursiveHashSetInt hashSet = new NonRecursiveHashSetInt(x.getLength()); + for (int i = 0; i < result.length; i++) { + hashSet.add(x.getDataAt(i)); + } + for (int i = table.getLength() - 1; i >= 0; i--) { + double val = table.getDataAt(i); + if (RRuntime.isNA(val) && hashSet.contains(RRuntime.INT_NA)) { + hashTable.put(RRuntime.INT_NA, i); + } else if (val == (int) val && hashSet.contains((int) val)) { + hashTable.put((int) val, i); + } + } + } else { + hashTable = new NonRecursiveHashMapInt(table.getLength()); + for (int i = table.getLength() - 1; i >= 0; i--) { + double xx = table.getDataAt(i); + if (RRuntime.isNA(xx)) { + hashTable.put(RRuntime.INT_NA, i); + } else if (xx == (int) xx) { + hashTable.put((int) xx, i); + } } } - } else { - for (int i = 0; i < length; i++) { - if (element.equals(table.getDataAt(i))) { - foundProfile.enter(); - return i + 1; + for (int i = 0; i < result.length; i++) { + int xx = x.getDataAt(i); + int index = hashTable.get(xx); + if (index != -1) { + result[i] = index + 1; + } else { + matchAll = false; } } + return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch)); } - notFoundProfile.enter(); - return nomatch; - } - @Specialization - protected RIntVector match(RAbstractStringVector x, RAbstractStringVector table, int nomatch, @SuppressWarnings("unused") Object incomparables) { - int[] result = initResult(x.getLength(), nomatch); - boolean matchAll = true; - NonRecursiveHashMapCharacter hashTable; - if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) { - hashTable = new NonRecursiveHashMapCharacter(x.getLength()); - NonRecursiveHashSetCharacter hashSet = new NonRecursiveHashSetCharacter(x.getLength()); + @Specialization + protected RIntVector match(RAbstractDoubleVector x, RAbstractDoubleVector table, int nomatch) { + int[] result = initResult(x.getLength(), nomatch); + boolean matchAll = true; + NonRecursiveHashMapDouble hashTable; + if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) { + hashTable = new NonRecursiveHashMapDouble(x.getLength()); + NonRecursiveHashSetDouble hashSet = new NonRecursiveHashSetDouble(x.getLength()); + for (int i = 0; i < result.length; i++) { + hashSet.add(x.getDataAt(i)); + } + for (int i = table.getLength() - 1; i >= 0; i--) { + double val = table.getDataAt(i); + if (hashSet.contains(val)) { + hashTable.put(val, i); + } + } + } else { + hashTable = new NonRecursiveHashMapDouble(table.getLength()); + for (int i = table.getLength() - 1; i >= 0; i--) { + hashTable.put(table.getDataAt(i), i); + } + } for (int i = 0; i < result.length; i++) { - hashSet.add(x.getDataAt(i)); + double xx = x.getDataAt(i); + int index = hashTable.get(xx); + if (index != -1) { + result[i] = index + 1; + } else { + matchAll = false; + } } - for (int i = table.getLength() - 1; i >= 0; i--) { - String val = table.getDataAt(i); - if (hashSet.contains(val)) { - hashTable.put(val, i); + return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch)); + } + + @Specialization + protected RIntVector match(RAbstractIntVector x, RAbstractLogicalVector table, int nomatch) { + int[] result = initResult(x.getLength(), nomatch); + boolean matchAll = true; + int[] values = {RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA}; + int[] indexes = new int[values.length]; + for (int i = 0; i < values.length; i++) { + byte value = (byte) values[i]; + for (int j = 0; j < table.getLength(); j++) { + if (table.getDataAt(j) == value) { + indexes[i] = j + 1; + break; + } } + values[i] = RRuntime.logical2int(value); } - } else { - hashTable = new NonRecursiveHashMapCharacter(table.getLength()); - for (int i = table.getLength() - 1; i >= 0; i--) { - hashTable.put(table.getDataAt(i), i); + for (int i = 0; i < result.length; i++) { + int xx = x.getDataAt(i); + boolean match = false; + for (int j = 0; j < values.length; j++) { + if (xx == values[j] && indexes[j] != 0) { + result[i] = indexes[j]; + match = true; + break; + } + } + matchAll &= match; + } + return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch)); + } + + @Specialization(guards = "x.getLength() == 1") + protected int matchSizeOne(RAbstractStringVector x, RAbstractStringVector table, int nomatch, + @Cached("create()") NAProfile naProfile, + @Cached("create()") BranchProfile foundProfile, + @Cached("create()") BranchProfile notFoundProfile) { + String element = x.getDataAt(0); + int length = table.getLength(); + if (naProfile.isNA(element)) { + for (int i = 0; i < length; i++) { + if (RRuntime.isNA(table.getDataAt(i))) { + foundProfile.enter(); + return i + 1; + } + } + } else { + for (int i = 0; i < length; i++) { + if (element.equals(table.getDataAt(i))) { + foundProfile.enter(); + return i + 1; + } + } } + notFoundProfile.enter(); + return nomatch; } - for (int i = 0; i < result.length; i++) { - String xx = x.getDataAt(i); - int index = hashTable.get(xx); - if (index != -1) { - result[i] = index + 1; + + @Specialization + protected RIntVector match(RAbstractStringVector x, RAbstractStringVector table, int nomatch) { + int[] result = initResult(x.getLength(), nomatch); + boolean matchAll = true; + NonRecursiveHashMapCharacter hashTable; + if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) { + hashTable = new NonRecursiveHashMapCharacter(x.getLength()); + NonRecursiveHashSetCharacter hashSet = new NonRecursiveHashSetCharacter(x.getLength()); + for (int i = 0; i < result.length; i++) { + hashSet.add(x.getDataAt(i)); + } + for (int i = table.getLength() - 1; i >= 0; i--) { + String val = table.getDataAt(i); + if (hashSet.contains(val)) { + hashTable.put(val, i); + } + } } else { - matchAll = false; + hashTable = new NonRecursiveHashMapCharacter(table.getLength()); + for (int i = table.getLength() - 1; i >= 0; i--) { + hashTable.put(table.getDataAt(i), i); + } } + for (int i = 0; i < result.length; i++) { + String xx = x.getDataAt(i); + int index = hashTable.get(xx); + if (index != -1) { + result[i] = index + 1; + } else { + matchAll = false; + } + } + return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch)); } - return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch)); - } - @Specialization - protected RIntVector match(RAbstractLogicalVector x, RAbstractStringVector table, int nomatch, Object incomparables) { - naCheck.enable(x); - return match(RClosures.createLogicalToStringVector(x), table, nomatch, incomparables); - } + @Specialization + protected RIntVector match(RAbstractLogicalVector x, RAbstractStringVector table, int nomatch, + @Cached("createBinaryProfile()") ConditionProfile isNAProfile) { + return match((RAbstractStringVector) x.castSafe(RType.Character, isNAProfile), table, nomatch); + } - @Specialization - protected RIntVector match(RAbstractRawVector x, RAbstractIntVector table, int nomatch, Object incomparables) { - naCheck.enable(x); - return match(RClosures.createRawToStringVector(x), RClosures.createIntToStringVector(table), nomatch, incomparables); - } + @Specialization + protected RIntVector match(RAbstractRawVector x, RAbstractIntVector table, int nomatch, + @Cached("createBinaryProfile()") ConditionProfile isNAProfile) { + return match((RAbstractStringVector) x.castSafe(RType.Character, isNAProfile), (RAbstractStringVector) table.castSafe(RType.Character, isNAProfile), nomatch); + } - @Specialization - protected RIntVector match(RAbstractIntVector x, RAbstractStringVector table, int nomatch, Object incomparables) { - naCheck.enable(x); - return match(RClosures.createIntToStringVector(x), table, nomatch, incomparables); - } + @Specialization + protected RIntVector match(RAbstractIntVector x, RAbstractStringVector table, int nomatch, + @Cached("createBinaryProfile()") ConditionProfile isNAProfile) { + return match((RAbstractStringVector) x.castSafe(RType.Character, isNAProfile), table, nomatch); + } - @Specialization - protected RIntVector match(RAbstractDoubleVector x, RAbstractStringVector table, int nomatch, Object incomparables) { - naCheck.enable(x); - return match(RClosures.createDoubleToStringVector(x), table, nomatch, incomparables); - } + @Specialization + protected RIntVector match(RAbstractDoubleVector x, RAbstractStringVector table, int nomatch, + @Cached("createBinaryProfile()") ConditionProfile isNAProfile) { + return match((RAbstractStringVector) x.castSafe(RType.Character, isNAProfile), table, nomatch); + } - @Specialization - protected RIntVector match(RAbstractLogicalVector x, RAbstractLogicalVector table, RAbstractIntVector nomatchVec, @SuppressWarnings("unused") Object incomparables) { - int nomatch = nomatchVec.getLength() == 0 ? RRuntime.INT_NA : nomatchVec.getDataAt(0); - int[] result = initResult(x.getLength(), nomatch); - boolean matchAll = true; - byte[] values = {RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA}; - int[] indexes = new int[values.length]; - for (int i = 0; i < values.length; i++) { - byte value = values[i]; - for (int j = 0; j < table.getLength(); j++) { - if (table.getDataAt(j) == value) { - indexes[i] = j + 1; - break; + @Specialization + protected RIntVector match(RAbstractLogicalVector x, RAbstractLogicalVector table, int nomatch) { + int[] result = initResult(x.getLength(), nomatch); + boolean matchAll = true; + byte[] values = {RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA}; + int[] indexes = new int[values.length]; + for (int i = 0; i < values.length; i++) { + byte value = values[i]; + for (int j = 0; j < table.getLength(); j++) { + if (table.getDataAt(j) == value) { + indexes[i] = j + 1; + break; + } } } - } - for (int i = 0; i < result.length; i++) { - byte xx = x.getDataAt(i); - boolean match = false; - for (int j = 0; j < values.length; j++) { - if (xx == values[j] && indexes[j] != 0) { - result[i] = indexes[j]; - match = true; - break; + for (int i = 0; i < result.length; i++) { + byte xx = x.getDataAt(i); + boolean match = false; + for (int j = 0; j < values.length; j++) { + if (xx == values[j] && indexes[j] != 0) { + result[i] = indexes[j]; + match = true; + break; + } } + matchAll &= match; } - matchAll &= match; + return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch)); } - return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch)); - } - @Specialization(guards = "!isStringVectorTable(table)") - protected RIntVector match(RAbstractStringVector x, RAbstractVector table, RAbstractIntVector nomatchVec, @SuppressWarnings("unused") Object incomparables) { - int nomatch = nomatchVec.getLength() == 0 ? RRuntime.INT_NA : nomatchVec.getDataAt(0); - int[] result = initResult(x.getLength(), nomatch); - boolean matchAll = true; - RAbstractStringVector stringTable = castString(table); - NonRecursiveHashMapCharacter hashTable = new NonRecursiveHashMapCharacter(table.getLength()); - for (int i = table.getLength() - 1; i >= 0; i--) { - hashTable.put(stringTable.getDataAt(i), i); - } - for (int i = 0; i < result.length; i++) { - String xx = x.getDataAt(i); - int index = hashTable.get(xx); - if (index != -1) { - result[i] = index + 1; - } else { - matchAll = false; + @Specialization(guards = "!isRAbstractStringVector(table)") + protected RIntVector match(RAbstractStringVector x, RAbstractVector table, int nomatch) { + int[] result = initResult(x.getLength(), nomatch); + boolean matchAll = true; + RAbstractStringVector stringTable = castString(table); + NonRecursiveHashMapCharacter hashTable = new NonRecursiveHashMapCharacter(table.getLength()); + for (int i = table.getLength() - 1; i >= 0; i--) { + hashTable.put(stringTable.getDataAt(i), i); } - } - return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch)); - } - - @Specialization - protected RIntVector match(RAbstractComplexVector x, RAbstractComplexVector table, RAbstractIntVector nomatchVec, @SuppressWarnings("unused") Object incomparables) { - int nomatch = nomatchVec.getLength() == 0 ? RRuntime.INT_NA : nomatchVec.getDataAt(0); - int[] result = initResult(x.getLength(), nomatch); - boolean matchAll = true; - NonRecursiveHashMapComplex hashTable; - if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) { - hashTable = new NonRecursiveHashMapComplex(x.getLength()); - NonRecursiveHashSetComplex hashSet = new NonRecursiveHashSetComplex(x.getLength()); for (int i = 0; i < result.length; i++) { - hashSet.add(x.getDataAt(i)); - } - for (int i = table.getLength() - 1; i >= 0; i--) { - RComplex val = table.getDataAt(i); - if (hashSet.contains(val)) { - hashTable.put(val, i); + String xx = x.getDataAt(i); + int index = hashTable.get(xx); + if (index != -1) { + result[i] = index + 1; + } else { + matchAll = false; } } - } else { - hashTable = new NonRecursiveHashMapComplex(table.getLength()); - for (int i = table.getLength() - 1; i >= 0; i--) { - hashTable.put(table.getDataAt(i), i); - } + return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch)); } - for (int i = 0; i < result.length; i++) { - RComplex xx = x.getDataAt(i); - int index = hashTable.get(xx); - if (index != -1) { - result[i] = index + 1; + + @Specialization + protected RIntVector match(RAbstractComplexVector x, RAbstractComplexVector table, int nomatch) { + int[] result = initResult(x.getLength(), nomatch); + boolean matchAll = true; + NonRecursiveHashMapComplex hashTable; + if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) { + hashTable = new NonRecursiveHashMapComplex(x.getLength()); + NonRecursiveHashSetComplex hashSet = new NonRecursiveHashSetComplex(x.getLength()); + for (int i = 0; i < result.length; i++) { + hashSet.add(x.getDataAt(i)); + } + for (int i = table.getLength() - 1; i >= 0; i--) { + RComplex val = table.getDataAt(i); + if (hashSet.contains(val)) { + hashTable.put(val, i); + } + } } else { - matchAll = false; + hashTable = new NonRecursiveHashMapComplex(table.getLength()); + for (int i = table.getLength() - 1; i >= 0; i--) { + hashTable.put(table.getDataAt(i), i); + } } + for (int i = 0; i < result.length; i++) { + RComplex xx = x.getDataAt(i); + int index = hashTable.get(xx); + if (index != -1) { + result[i] = index + 1; + } else { + matchAll = false; + } + } + return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch)); } - return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch)); - } - - @Specialization - @SuppressWarnings("unused") - protected RIntVector match(RFunction x, Object table, int nomatch, Object incomparables) { - throw RError.error(this, MATCH_VECTOR_ARGS); - } - - @Specialization - @SuppressWarnings("unused") - protected RIntVector match(Object x, RFunction table, int nomatch, Object incomparables) { - throw RError.error(this, MATCH_VECTOR_ARGS); - } - - protected boolean isStringVectorTable(RAbstractVector table) { - return table.getElementClass() == String.class; - } - - @Child private InheritsCheckNode factorInheritsCheck = new InheritsCheckNode(RRuntime.CLASS_FACTOR); - protected boolean isFactor(Object o) { - return factorInheritsCheck.execute(o); - } - - private static int[] initResult(int length, int nomatch) { - int[] result = new int[length]; - Arrays.fill(result, nomatch); - return result; - } + private static int[] initResult(int length, int nomatch) { + int[] result = new int[length]; + Arrays.fill(result, nomatch); + return result; + } - /** - * Set the "complete" status. If {@code nomatch} is not NA (uncommon), then the result vector is - * always COMPLETE, otherwise it is INCOMPLETE unless everything matched. - */ - private static boolean setCompleteState(boolean matchAll, int nomatch) { - return nomatch != RRuntime.INT_NA || matchAll ? RDataFactory.COMPLETE_VECTOR : RDataFactory.INCOMPLETE_VECTOR; - } + /** + * Set the "complete" status. If {@code nomatch} is not NA (uncommon), then the result + * vector is always COMPLETE, otherwise it is INCOMPLETE unless everything matched. + */ + private static boolean setCompleteState(boolean matchAll, int nomatch) { + return nomatch != RRuntime.INT_NA || matchAll ? RDataFactory.COMPLETE_VECTOR : RDataFactory.INCOMPLETE_VECTOR; + } - // simple implementations of non-recursive hash-maps to enable compilation - // TODO: consider replacing with a more efficient library implementation + // simple implementations of non-recursive hash-maps to enable compilation + // TODO: consider replacing with a more efficient library implementation - private abstract static class NonRecursiveHashMap { + private abstract static class NonRecursiveHashMap { - protected final int[] values; - protected int naValue; + protected final int[] values; + protected int naValue; - protected NonRecursiveHashMap(int entryCount) { - int capacity = Math.max(entryCount * 3 / 2, 1); - values = new int[Integer.highestOneBit(capacity) << 1]; - } + protected NonRecursiveHashMap(int entryCount) { + int capacity = Math.max(entryCount * 3 / 2, 1); + values = new int[Integer.highestOneBit(capacity) << 1]; + } - protected int index(int hash) { - // Multiply by -127 - return ((hash << 1) - (hash << 8)) & (values.length - 1); + protected int index(int hash) { + // Multiply by -127 + return ((hash << 1) - (hash << 8)) & (values.length - 1); + } } - } - private static final class NonRecursiveHashMapCharacter extends NonRecursiveHashMap { + private static final class NonRecursiveHashMapCharacter extends NonRecursiveHashMap { - private final String[] keys; + private final String[] keys; - NonRecursiveHashMapCharacter(int approxCapacity) { - super(approxCapacity); - keys = new String[values.length]; - } + NonRecursiveHashMapCharacter(int approxCapacity) { + super(approxCapacity); + keys = new String[values.length]; + } - public boolean put(String key, int value) { - assert value >= 0; - if (RRuntime.isNA(key)) { - boolean ret = naValue == 0; - naValue = value + 1; - return ret; - } else { - int ind = index(key.hashCode()); - while (true) { - if (values[ind] == 0) { - keys[ind] = key; - values[ind] = value + 1; - return false; - } else if (key.equals(keys[ind])) { - values[ind] = value + 1; - return true; - } else { - ind++; - if (ind == values.length) { - ind = 0; + public boolean put(String key, int value) { + assert value >= 0; + if (RRuntime.isNA(key)) { + boolean ret = naValue == 0; + naValue = value + 1; + return ret; + } else { + int ind = index(key.hashCode()); + while (true) { + if (values[ind] == 0) { + keys[ind] = key; + values[ind] = value + 1; + return false; + } else if (key.equals(keys[ind])) { + values[ind] = value + 1; + return true; + } else { + ind++; + if (ind == values.length) { + ind = 0; + } } } } } - } - public int get(String key) { - if (RRuntime.isNA(key)) { - return naValue - 1; - } else { - int ind = index(key.hashCode()); - int firstInd = ind; - while (true) { - if (key.equals(keys[ind])) { - return values[ind] - 1; - } else { - ind++; - if (ind == values.length) { - ind = 0; - } - if (ind == firstInd || values[ind] == 0) { - return -1; + public int get(String key) { + if (RRuntime.isNA(key)) { + return naValue - 1; + } else { + int ind = index(key.hashCode()); + int firstInd = ind; + while (true) { + if (key.equals(keys[ind])) { + return values[ind] - 1; + } else { + ind++; + if (ind == values.length) { + ind = 0; + } + if (ind == firstInd || values[ind] == 0) { + return -1; + } } } } } } - } - - private static final class NonRecursiveHashMapComplex extends NonRecursiveHashMap { - private final RComplex[] keys; - - NonRecursiveHashMapComplex(int approxCapacity) { - super(approxCapacity); - keys = new RComplex[values.length]; - } - - public boolean put(RComplex key, int value) { - assert value >= 0; - if (RRuntime.isNA(key)) { - boolean ret = naValue == 0; - naValue = value + 1; - return ret; - } else { - int ind = index(key.hashCode()); - while (true) { - if (values[ind] == 0) { - keys[ind] = key; - values[ind] = value + 1; - return false; - } else if (key.equals(keys[ind])) { - values[ind] = value + 1; - return true; - } else { - ind++; - if (ind == values.length) { - ind = 0; + private static final class NonRecursiveHashMapComplex extends NonRecursiveHashMap { + + private final RComplex[] keys; + + NonRecursiveHashMapComplex(int approxCapacity) { + super(approxCapacity); + keys = new RComplex[values.length]; + } + + public boolean put(RComplex key, int value) { + assert value >= 0; + if (RRuntime.isNA(key)) { + boolean ret = naValue == 0; + naValue = value + 1; + return ret; + } else { + int ind = index(key.hashCode()); + while (true) { + if (values[ind] == 0) { + keys[ind] = key; + values[ind] = value + 1; + return false; + } else if (key.equals(keys[ind])) { + values[ind] = value + 1; + return true; + } else { + ind++; + if (ind == values.length) { + ind = 0; + } } } } } - } - public int get(RComplex key) { - if (RRuntime.isNA(key)) { - return naValue - 1; - } else { - int ind = index(key.hashCode()); - int firstInd = ind; - while (true) { - if (key.equals(keys[ind])) { - return values[ind] - 1; - } else { - ind++; - if (ind == values.length) { - ind = 0; - } - if (ind == firstInd || values[ind] == 0) { - return -1; + public int get(RComplex key) { + if (RRuntime.isNA(key)) { + return naValue - 1; + } else { + int ind = index(key.hashCode()); + int firstInd = ind; + while (true) { + if (key.equals(keys[ind])) { + return values[ind] - 1; + } else { + ind++; + if (ind == values.length) { + ind = 0; + } + if (ind == firstInd || values[ind] == 0) { + return -1; + } } } } } } - } - - private static final class NonRecursiveHashMapDouble extends NonRecursiveHashMap { - - private final double[] keys; - private int nanValue; - - NonRecursiveHashMapDouble(int approxCapacity) { - super(approxCapacity); - keys = new double[values.length]; - Arrays.fill(keys, RRuntime.DOUBLE_NA); - } - public boolean put(double key, int value) { - assert value >= 0; - if (RRuntime.isNA(key)) { - boolean ret = naValue == 0; - naValue = value + 1; - return ret; - } else if (Double.isNaN(key)) { - boolean ret = nanValue == 0; - nanValue = value + 1; - return ret; - } else { - int ind = index(Double.hashCode(key)); - while (true) { - if (values[ind] == 0) { - keys[ind] = key; - values[ind] = value + 1; - return false; - } else if (key == keys[ind]) { - values[ind] = value + 1; - return true; - } else { - ind++; - if (ind == values.length) { - ind = 0; + private static final class NonRecursiveHashMapDouble extends NonRecursiveHashMap { + + private final double[] keys; + private int nanValue; + + NonRecursiveHashMapDouble(int approxCapacity) { + super(approxCapacity); + keys = new double[values.length]; + Arrays.fill(keys, RRuntime.DOUBLE_NA); + } + + public boolean put(double key, int value) { + assert value >= 0; + if (RRuntime.isNA(key)) { + boolean ret = naValue == 0; + naValue = value + 1; + return ret; + } else if (Double.isNaN(key)) { + boolean ret = nanValue == 0; + nanValue = value + 1; + return ret; + } else { + int ind = index(Double.hashCode(key)); + while (true) { + if (values[ind] == 0) { + keys[ind] = key; + values[ind] = value + 1; + return false; + } else if (key == keys[ind]) { + values[ind] = value + 1; + return true; + } else { + ind++; + if (ind == values.length) { + ind = 0; + } } } } } - } - public int get(double key) { - if (RRuntime.isNA(key)) { - return naValue - 1; - } else if (Double.isNaN(key)) { - return nanValue - 1; - } else { - int ind = index(Double.hashCode(key)); - int firstInd = ind; - while (true) { - if (key == keys[ind]) { - return values[ind] - 1; - } else { - ind++; - if (ind == values.length) { - ind = 0; - } - if (ind == firstInd || values[ind] == 0) { - return -1; + public int get(double key) { + if (RRuntime.isNA(key)) { + return naValue - 1; + } else if (Double.isNaN(key)) { + return nanValue - 1; + } else { + int ind = index(Double.hashCode(key)); + int firstInd = ind; + while (true) { + if (key == keys[ind]) { + return values[ind] - 1; + } else { + ind++; + if (ind == values.length) { + ind = 0; + } + if (ind == firstInd || values[ind] == 0) { + return -1; + } } } } } } - } - private static final class NonRecursiveHashMapInt extends NonRecursiveHashMap { - - private final int[] keys; - - NonRecursiveHashMapInt(int approxCapacity) { - super(approxCapacity); - keys = new int[values.length]; - Arrays.fill(keys, RRuntime.INT_NA); - } - - public boolean put(int key, int value) { - assert value >= 0; - if (RRuntime.isNA(key)) { - boolean ret = naValue == 0; - naValue = value + 1; - return ret; - } else { - int ind = index(Integer.hashCode(key)); - while (true) { - if (values[ind] == 0) { - keys[ind] = key; - values[ind] = value + 1; - return false; - } else if (key == keys[ind]) { - values[ind] = value + 1; - return true; - } else { - ind++; - if (ind == values.length) { - ind = 0; + private static final class NonRecursiveHashMapInt extends NonRecursiveHashMap { + + private final int[] keys; + + NonRecursiveHashMapInt(int approxCapacity) { + super(approxCapacity); + keys = new int[values.length]; + Arrays.fill(keys, RRuntime.INT_NA); + } + + public boolean put(int key, int value) { + assert value >= 0; + if (RRuntime.isNA(key)) { + boolean ret = naValue == 0; + naValue = value + 1; + return ret; + } else { + int ind = index(Integer.hashCode(key)); + while (true) { + if (values[ind] == 0) { + keys[ind] = key; + values[ind] = value + 1; + return false; + } else if (key == keys[ind]) { + values[ind] = value + 1; + return true; + } else { + ind++; + if (ind == values.length) { + ind = 0; + } } } } } - } - public int get(int key) { - if (RRuntime.isNA(key)) { - return naValue - 1; - } else { - int ind = index(Integer.hashCode(key)); - int firstInd = ind; - while (true) { - if (key == keys[ind]) { - return values[ind] - 1; - } else { - ind++; - if (ind == values.length) { - ind = 0; - } - if (ind == firstInd || values[ind] == 0) { - return -1; + public int get(int key) { + if (RRuntime.isNA(key)) { + return naValue - 1; + } else { + int ind = index(Integer.hashCode(key)); + int firstInd = ind; + while (true) { + if (key == keys[ind]) { + return values[ind] - 1; + } else { + ind++; + if (ind == values.length) { + ind = 0; + } + if (ind == firstInd || values[ind] == 0) { + return -1; + } } } } } } - } - private static class NonRecursiveHashSetInt { - private final NonRecursiveHashMapInt map; + private static class NonRecursiveHashSetInt { + private final NonRecursiveHashMapInt map; - NonRecursiveHashSetInt(int approxCapacity) { - map = new NonRecursiveHashMapInt(approxCapacity); - } + NonRecursiveHashSetInt(int approxCapacity) { + map = new NonRecursiveHashMapInt(approxCapacity); + } - public boolean add(int value) { - return map.put(value, 1); - } + public boolean add(int value) { + return map.put(value, 1); + } - public boolean contains(int value) { - return map.get(value) == 1 ? true : false; + public boolean contains(int value) { + return map.get(value) == 1 ? true : false; + } } - } - private static class NonRecursiveHashSetDouble { - private final NonRecursiveHashMapDouble map; + private static class NonRecursiveHashSetDouble { + private final NonRecursiveHashMapDouble map; - NonRecursiveHashSetDouble(int approxCapacity) { - map = new NonRecursiveHashMapDouble(approxCapacity); - } + NonRecursiveHashSetDouble(int approxCapacity) { + map = new NonRecursiveHashMapDouble(approxCapacity); + } - public boolean add(double value) { - return map.put(value, 1); - } + public boolean add(double value) { + return map.put(value, 1); + } - public boolean contains(double value) { - return map.get(value) == 1 ? true : false; + public boolean contains(double value) { + return map.get(value) == 1 ? true : false; + } } - } - private static class NonRecursiveHashSetCharacter { - private final NonRecursiveHashMapCharacter map; + private static class NonRecursiveHashSetCharacter { + private final NonRecursiveHashMapCharacter map; - NonRecursiveHashSetCharacter(int approxCapacity) { - map = new NonRecursiveHashMapCharacter(approxCapacity); - } + NonRecursiveHashSetCharacter(int approxCapacity) { + map = new NonRecursiveHashMapCharacter(approxCapacity); + } - public boolean add(String value) { - return map.put(value, 1); - } + public boolean add(String value) { + return map.put(value, 1); + } - public boolean contains(String value) { - return map.get(value) == 1 ? true : false; + public boolean contains(String value) { + return map.get(value) == 1 ? true : false; + } } - } - private static class NonRecursiveHashSetComplex { - private final NonRecursiveHashMapComplex map; + private static class NonRecursiveHashSetComplex { + private final NonRecursiveHashMapComplex map; - NonRecursiveHashSetComplex(int approxCapacity) { - map = new NonRecursiveHashMapComplex(approxCapacity); - } + NonRecursiveHashSetComplex(int approxCapacity) { + map = new NonRecursiveHashMapComplex(approxCapacity); + } - public boolean add(RComplex value) { - return map.put(value, 1); - } + public boolean add(RComplex value) { + return map.put(value, 1); + } - public boolean contains(RComplex value) { - return map.get(value) == 1 ? true : false; + public boolean contains(RComplex value) { + return map.get(value) == 1 ? true : false; + } } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java index 170e79418089d9fad4aabc809aa050a0bbc45eae..0598b8eda2e33ec7e57c12af1151a9eaa4f68421 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java @@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; +import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.SUBSTITUTE; @@ -39,7 +40,6 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.RRootNode; -import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.MatchArgNodeGen.MatchArgInternalNodeGen; import com.oracle.truffle.r.nodes.function.FormalArguments; @@ -63,7 +63,7 @@ import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @RBuiltin(name = "match.arg", kind = SUBSTITUTE, parameterNames = {"arg", "choices", "several.ok"}, nonEvalArgs = {0}, behavior = COMPLEX) -public abstract class MatchArg extends RBuiltinNode { +public abstract class MatchArg extends RBuiltinNode.Arg3 { static { Casts.noCasts(MatchArg.class); @@ -80,20 +80,14 @@ public abstract class MatchArg extends RBuiltinNode { @Child private PMatch pmatch = PMatchNodeGen.create(); @Child private Identical identical = IdenticalNodeGen.create(); - @Children private final CastNode[] casts; - - { - CastBuilder builder = new CastBuilder(); - builder.arg(0).asStringVector(); - builder.arg(1).allowMissing().mustBe(stringValue()).asStringVector(); - builder.arg(2).mustBe(logicalValue()).asLogicalVector().findFirst().map(toBoolean()); - this.casts = builder.getCasts(); - } + @Child private CastNode argCast = newCastBuilder().asStringVector().buildCastNode(); + @Child private CastNode choicesCast = newCastBuilder().allowMissing().mustBe(stringValue()).asStringVector().buildCastNode(); + @Child private CastNode severalOKCast = newCastBuilder().mustBe(logicalValue()).asLogicalVector().findFirst().map(toBoolean()).buildCastNode(); public abstract Object execute(Object arg, Object choices, Object severalOK); public final Object castAndExecute(Object arg, Object choices, Object severalOK) { - return execute(casts[0].execute(arg), casts[1].execute(choices), casts[2].execute(severalOK)); + return execute(argCast.doCast(arg), choicesCast.doCast(choices), severalOKCast.doCast(severalOK)); } @Specialization @@ -107,7 +101,7 @@ public abstract class MatchArg extends RBuiltinNode { CompilerDirectives.transferToInterpreter(); StringBuilder choicesString = new StringBuilder(); for (int i = 0; i < choices.getLength(); i++) { - choicesString.append(i == 0 ? "" : ", ").append(RRuntime.quoteString(choices.getDataAt(i), false)); + choicesString.append(i == 0 ? "" : ", ").append(RRuntime.escapeString(choices.getDataAt(i), false, true)); } throw RError.error(this, Message.ARG_ONE_OF, "arg", choicesString); } @@ -233,6 +227,6 @@ public abstract class MatchArg extends RBuiltinNode { @SuppressWarnings("unused") @Fallback protected Object matchArgFallback(Object arg, Object choices, Object severalOK) { - throw RError.error(this, Message.GENERIC, "too many different names in match.arg"); + throw error(Message.GENERIC, "too many different names in match.arg"); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java index 69cb73a3f14f1f5e8d862ff172407a8c3ef575dc..00ba7a002e1d50f9bdce1032ff260260630b6d7d 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java @@ -51,13 +51,14 @@ import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.RTypes; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @RBuiltin(name = "match.fun", kind = SUBSTITUTE, parameterNames = {"fun", "descend"}, nonEvalArgs = 0, behavior = COMPLEX) -public abstract class MatchFun extends RBuiltinNode { +public abstract class MatchFun extends RBuiltinNode.Arg2 { @Override public Object[] getDefaultParameterValues() { @@ -118,7 +119,7 @@ public abstract class MatchFun extends RBuiltinNode { return (RFunction) result; } else { CompilerDirectives.transferToInterpreter(); - throw RError.error(outer, RError.Message.NON_FUNCTION, RDeparse.deparse(result)); + throw outer.error(RError.Message.NON_FUNCTION, RDeparse.deparse(result)); } } @@ -149,10 +150,10 @@ public abstract class MatchFun extends RBuiltinNode { } @TruffleBoundary - private static Object slowPathLookup(String name, MaterializedFrame frame, boolean descend) { + private Object slowPathLookup(String name, MaterializedFrame frame, boolean descend) { Object result = descend ? ReadVariableNode.lookupFunction(name, frame) : ReadVariableNode.lookupAny(name, frame, false); if (result == null) { - throw RError.error(RError.SHOW_CALLER, descend ? RError.Message.UNKNOWN_FUNCTION : RError.Message.UNKNOWN_OBJECT, name); + throw outer.error(descend ? RError.Message.UNKNOWN_FUNCTION : RError.Message.UNKNOWN_OBJECT, name); } return result; } @@ -179,7 +180,7 @@ public abstract class MatchFun extends RBuiltinNode { return checkResult(slowPathLookup(lookupName, getCallerFrame.execute(frame), descend)); } else { CompilerDirectives.transferToInterpreter(); - throw RError.error(outer, RError.Message.NOT_FUNCTION, RDeparse.deparseSyntaxElement(rep)); + throw outer.error(RError.Message.NOT_FUNCTION, RDeparse.deparseSyntaxElement(rep)); } } @@ -194,7 +195,7 @@ public abstract class MatchFun extends RBuiltinNode { if (slot == null) { return null; } else { - return frame.getValue(slot); + return FrameSlotChangeMonitor.getValue(slot, frame); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java index 90f7823259a653c13679dd74346ac6f428e2ee77..161972a2025762f48eb886d98d443d34169fd7e2 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java @@ -42,7 +42,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "matrix", kind = INTERNAL, parameterNames = {"data", "nrow", "ncol", "byrow", "dimnames", "missingNr", "missingNc"}, behavior = PURE) -public abstract class Matrix extends RBuiltinNode { +public abstract class Matrix extends RBuiltinNode.Arg7 { @Child private Transpose transpose; @Child private UpdateDimNames updateDimNames; @@ -130,7 +130,7 @@ public abstract class Matrix extends RBuiltinNode { return new int[]{size, 1}; } else if (nrowGivenNcolMissing.profile(!missingNr && missingNc)) { if (nrow == 0 && size > 0) { - throw RError.error(this, RError.Message.NROW_ZERO); + throw error(RError.Message.NROW_ZERO); } if (empty.profile(size == 0)) { return new int[]{nrow, 0}; @@ -139,7 +139,7 @@ public abstract class Matrix extends RBuiltinNode { } } else if (nrowMissingNcolGiven.profile(missingNr && !missingNc)) { if (ncol == 0 && size > 0) { - throw RError.error(this, RError.Message.NCOL_ZERO); + throw error(RError.Message.NCOL_ZERO); } if (empty.profile(size == 0)) { return new int[]{0, ncol}; @@ -157,7 +157,7 @@ public abstract class Matrix extends RBuiltinNode { return new int[]{1, size}; } else if (nrowGivenNcolMissing.profile(!missingNr && missingNc)) { if (nrow == 0 && size > 0) { - throw RError.error(this, RError.Message.NROW_ZERO); + throw error(RError.Message.NROW_ZERO); } if (empty.profile(size == 0)) { return new int[]{0, nrow}; @@ -167,7 +167,7 @@ public abstract class Matrix extends RBuiltinNode { } } else if (nrowMissingNcolGiven.profile(missingNr && !missingNc)) { if (ncol == 0 && size > 0) { - throw RError.error(this, RError.Message.NCOL_ZERO); + throw error(RError.Message.NCOL_ZERO); } if (empty.profile(size == 0)) { return new int[]{ncol, 0}; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Max.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Max.java index 2e898cf52915435168f803976d8ac0e8abf10098..6c3556db61b99058eb0ce292cdc5ea1522b12b79 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Max.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Max.java @@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; @RBuiltin(name = "max", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE) -public abstract class Max extends RBuiltinNode { +public abstract class Max extends RBuiltinNode.Arg2 { private static final ReduceSemantics semantics = new ReduceSemantics(RRuntime.INT_MIN_VALUE, Double.NEGATIVE_INFINITY, false, RError.Message.NO_NONMISSING_MAX, RError.Message.NO_NONMISSING_MAX_NA, false, true); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.java index dc04a0b92877a108aaf3d35057386b54bf16a0c8..3cd1cf689cf244c73adb9abffd2365191b523a40 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.java @@ -39,7 +39,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; @RBuiltin(name = "mean", kind = INTERNAL, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE) -public abstract class Mean extends RBuiltinNode { +public abstract class Mean extends RBuiltinNode.Arg1 { private final BranchProfile emptyProfile = BranchProfile.create(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java index 45dd58eeec87d84b64950d746ac2e13c585c7000..c2ededbc786e8ec0835efb45edd40b2f4176718c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java @@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; * Note: invoked from merge.data.frame. */ @RBuiltin(name = "merge", kind = INTERNAL, parameterNames = {"xinds", "yinds", "all.x", "all.y"}, behavior = PURE) -public abstract class Merge extends RBuiltinNode { +public abstract class Merge extends RBuiltinNode.Arg4 { static { Casts casts = new Casts(Merge.class); @@ -50,7 +50,7 @@ public abstract class Merge extends RBuiltinNode { } private static void addLogicalCast(Casts casts, String name) { - casts.arg(name).defaultError(INVALID_LOGICAL, "all.x").mustBe(numericValue()).asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg(name).defaultError(INVALID_LOGICAL, "all.x").mustBe(numericValue()).asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } private static void isortWithIndex(int[] x, int[] indx, int n) { @@ -142,7 +142,7 @@ public abstract class Merge extends RBuiltinNode { dnans += ((double) (nnx - i)) * (nny - j); } if (dnans > RRuntime.INT_MAX_VALUE) { - throw RError.error(this, RError.Message.GENERIC, "number of rows in the result exceeds maximum vector length"); + throw error(RError.Message.GENERIC, "number of rows in the result exceeds maximum vector length"); } int nans = (int) dnans; @@ -151,28 +151,24 @@ public abstract class Merge extends RBuiltinNode { int[] ansXData = new int[nans]; int[] ansYData = new int[nans]; - RList ans = RDataFactory.createList(new Object[4], RDataFactory.createStringVector(new String[]{"xi", "yi", "x.alone", "y.alone"}, RDataFactory.COMPLETE_VECTOR)); - ans.updateDataAt(0, RDataFactory.createIntVector(ansXData, RDataFactory.COMPLETE_VECTOR), null); - ans.updateDataAt(1, RDataFactory.createIntVector(ansYData, RDataFactory.COMPLETE_VECTOR), null); + Object[] ansData = new Object[]{RDataFactory.createIntVector(ansXData, RDataFactory.COMPLETE_VECTOR), RDataFactory.createIntVector(ansYData, RDataFactory.COMPLETE_VECTOR), RNull.instance, + RNull.instance}; + RList ans = RDataFactory.createList(ansData, RDataFactory.createStringVector(new String[]{"xi", "yi", "x.alone", "y.alone"}, RDataFactory.COMPLETE_VECTOR)); if (allX) { int[] xLoneData = new int[nxLone]; - ans.updateDataAt(2, RDataFactory.createIntVector(xLoneData, RDataFactory.COMPLETE_VECTOR), null); + ansData[2] = RDataFactory.createIntVector(xLoneData, RDataFactory.COMPLETE_VECTOR); for (int i = 0, ll = 0; i < nxLone; i++) { xLoneData[ll++] = ix[i]; } - } else { - ans.updateDataAt(2, RNull.instance, null); } if (allY) { int[] yLoneData = new int[nyLone]; - ans.updateDataAt(3, RDataFactory.createIntVector(yLoneData, RDataFactory.COMPLETE_VECTOR), null); + ansData[3] = RDataFactory.createIntVector(yLoneData, RDataFactory.COMPLETE_VECTOR); for (int i = 0, ll = 0; i < nyLone; i++) { yLoneData[ll++] = iy[i]; } - } else { - ans.updateDataAt(3, RNull.instance, null); } j = nyLone; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Min.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Min.java index 09b73c273d4219428e837d870bca7555e078fdb5..1f14fbafc416a9542bbf07fbae9a57a5055ff25b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Min.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Min.java @@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; @RBuiltin(name = "min", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE) -public abstract class Min extends RBuiltinNode { +public abstract class Min extends RBuiltinNode.Arg2 { private static final ReduceSemantics semantics = new ReduceSemantics(RRuntime.INT_MAX_VALUE, Double.POSITIVE_INFINITY, false, RError.Message.NO_NONMISSING_MIN, RError.Message.NO_NONMISSING_MIN_NA, false, true); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java index a814219f4e4235d65d4bf9c1fce65aa6517b0e5b..355b1f84a311a425b20bae054bd485b132442398 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.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 @@ -32,7 +32,6 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.signature.MissingNode; import com.oracle.truffle.r.nodes.function.signature.MissingNode.MissingCheckCache; -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.builtins.RBuiltin; @@ -45,7 +44,12 @@ import com.oracle.truffle.r.runtime.data.RPromise; * correctly, because the varargs are already handled by the argument matching. */ @RBuiltin(name = "missing", kind = PRIMITIVE, nonEvalArgs = 0, parameterNames = {"x"}, behavior = COMPLEX) -public abstract class Missing extends RBuiltinNode { +public abstract class Missing extends RBuiltinNode.Arg1 { + + static { + Casts casts = new Casts(Missing.class); + casts.arg("x").allowMissing(); + } @Specialization protected byte missing(VirtualFrame frame, RPromise promise, @@ -53,7 +57,7 @@ public abstract class Missing extends RBuiltinNode { String symbol = promise.getClosure().asSymbol(); if (symbol == null) { CompilerDirectives.transferToInterpreter(); - throw RError.error(this, Message.INVALID_USE, "missing"); + throw error(Message.INVALID_USE, "missing"); } return RRuntime.asLogical(cache.execute(frame, symbol)); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NArgs.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NArgs.java index 6a166f0a124262961f583bac969c032b8af4936a..06edb6da08b1a31a0b462cb3e025b85c35a702a5 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NArgs.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NArgs.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 @@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.data.RPromise; // TODO Figure out how to distinguish f(,,a) from f(a) - RMissing is used in both contexts @RBuiltin(name = "nargs", kind = PRIMITIVE, parameterNames = {}, behavior = RBehavior.READS_FRAME) -public abstract class NArgs extends RBuiltinNode { +public abstract class NArgs extends RBuiltinNode.Arg0 { private final BranchProfile isPromiseProfile = BranchProfile.create(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java index b55927dda5324e900eee919da7ca7562f329fb30..8c6b7d81d146cc79ab669752db13765b6742b111 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java @@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asIntegerVector; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asStringVector; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lengthGt; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -38,6 +39,7 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNa import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -49,43 +51,52 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; // TODO interpret "type" and "allowNA" arguments @RBuiltin(name = "nchar", kind = INTERNAL, parameterNames = {"x", "type", "allowNA", "keepNA"}, behavior = PURE) -public abstract class NChar extends RBuiltinNode { +public abstract class NChar extends RBuiltinNode.Arg4 { + private static final String[] TYPES = new String[]{"bytes", "chars", "width"}; + private static final int TYPE_BYTES = 0; + private static final int TYPE_CHARS = 1; + private static final int TYPE_WIDTH = 2; static { Casts casts = new Casts(NChar.class); - casts.arg("x").allowNull().mapIf(integerValue(), asIntegerVector(), asStringVector(true, false, false)); - casts.arg("type").asStringVector().findFirst(); - casts.arg("allowNA").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).map(toBoolean()); - casts.arg("keepNA").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); + casts.arg("x").mustNotBeMissing().mapIf(integerValue(), asIntegerVector(), asStringVector(true, false, false)); + casts.arg("type").asStringVector().findFirst().mustBe(lengthGt(0)); + casts.arg("allowNA").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); + casts.arg("keepNA").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean()); } @SuppressWarnings("unused") @Specialization - protected RIntVector nchar(RNull value, String type, boolean allowNA, boolean keepNA) { + protected RIntVector nchar(RNull value, String type, byte allowNA, boolean keepNA) { return RDataFactory.createEmptyIntVector(); } @SuppressWarnings("unused") @Specialization - protected RIntVector ncharInt(RAbstractIntVector vector, String type, boolean allowNA, boolean keepNA, + protected RIntVector ncharInt(RAbstractIntVector vector, String type, byte allowNA, boolean keepNAIn, @Cached("createCountingProfile()") LoopConditionProfile loopProfile, @Cached("createBinaryProfile()") ConditionProfile nullDimNamesProfile, + @Cached("createBinaryProfile()") ConditionProfile keepNAProfile, @Cached("create()") GetDimAttributeNode getDimNode, @Cached("create()") SetDimNamesAttributeNode setDimNamesNode, @Cached("create()") GetDimNamesAttributeNode getDimNamesNode, @Cached("create()") GetNamesAttributeNode getNamesNode) { + convertType(type); + boolean keepNA = keepNAProfile.profile(keepNAIn); int len = vector.getLength(); int[] result = new int[len]; + boolean isComplete = true; loopProfile.profileCounted(len); for (int i = 0; loopProfile.inject(i < len); i++) { int x = vector.getDataAt(i); if (x == RRuntime.INT_NA) { - result[i] = 2; + result[i] = keepNA ? RRuntime.INT_NA : 2; + isComplete = !keepNA; } else { result[i] = (int) (Math.log10(x) + 1); // not the fastest one } } - RIntVector resultVector = RDataFactory.createIntVector(result, true, getDimNode.getDimensions(vector), getNamesNode.getNames(vector)); + RIntVector resultVector = RDataFactory.createIntVector(result, isComplete, getDimNode.getDimensions(vector), getNamesNode.getNames(vector)); RList dimNames = getDimNamesNode.getDimNames(vector); if (nullDimNamesProfile.profile(dimNames != null)) { setDimNamesNode.setDimNames(resultVector, dimNames); @@ -95,24 +106,44 @@ public abstract class NChar extends RBuiltinNode { @SuppressWarnings("unused") @Specialization - protected RIntVector nchar(RAbstractStringVector vector, String type, boolean allowNA, boolean keepNA, + protected RIntVector nchar(RAbstractStringVector vector, String type, byte allowNA, boolean keepNAIn, @Cached("createCountingProfile()") LoopConditionProfile loopProfile, @Cached("createBinaryProfile()") ConditionProfile nullDimNamesProfile, + @Cached("createBinaryProfile()") ConditionProfile keepNAProfile, @Cached("create()") GetDimAttributeNode getDimNode, @Cached("create()") SetDimNamesAttributeNode setDimNamesNode, @Cached("create()") GetDimNamesAttributeNode getDimNamesNode, @Cached("create()") GetNamesAttributeNode getNamesNode) { + convertType(type); + boolean keepNA = keepNAProfile.profile(keepNAIn); int len = vector.getLength(); int[] result = new int[len]; + boolean isComplete = true; loopProfile.profileCounted(len); for (int i = 0; loopProfile.inject(i < len); i++) { - result[i] = vector.getDataAt(i).length(); + String item = vector.getDataAt(i); + if (RRuntime.isNA(item)) { + result[i] = keepNA ? RRuntime.INT_NA : 2; + isComplete = !keepNA; + } else { + result[i] = item.length(); + } } - RIntVector resultVector = RDataFactory.createIntVector(result, true, getDimNode.getDimensions(vector), getNamesNode.getNames(vector)); + RIntVector resultVector = RDataFactory.createIntVector(result, isComplete, getDimNode.getDimensions(vector), getNamesNode.getNames(vector)); RList dimNames = getDimNamesNode.getDimNames(vector); if (nullDimNamesProfile.profile(dimNames != null)) { setDimNamesNode.setDimNames(resultVector, dimNames); } return resultVector; } + + private int convertType(String type) { + // The string in type is matched partially e.g. 'c' is 'chars', but 'charsxyz' is invalid + for (int i = 0; i < TYPES.length; i++) { + if (type.length() <= TYPES[i].length() && TYPES[i].startsWith(type)) { + return i; + } + } + throw error(Message.INVALID_ARGUMENT, "type"); + } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NGetText.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NGetText.java index d72cda8937c3980ac6688c9fa9fa908234c52a48..b3959ceda785fe66167eb2edbc0e146ec80ee042 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NGetText.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NGetText.java @@ -34,7 +34,7 @@ import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "ngettext", kind = INTERNAL, parameterNames = {"n", "msg1", "msg2", "domain"}, behavior = COMPLEX) -public abstract class NGetText extends RBuiltinNode { +public abstract class NGetText extends RBuiltinNode.Arg4 { static { Casts casts = new Casts(NGetText.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java index bfd884b2fb2ec7e60ffaf504df65c2517ab53d7d..741fd707d609a55def54d55a22ea9f646e9fb288 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java @@ -28,20 +28,22 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "nzchar", kind = PRIMITIVE, parameterNames = {"x", "keepNA"}, behavior = PURE) -public abstract class NZChar extends RBuiltinNode { +public abstract class NZChar extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(NZChar.class); casts.arg("x").asStringVector(); - casts.arg("keepNA").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); + casts.arg("keepNA").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean(false)); } private static byte isNonZeroLength(String s) { @@ -68,4 +70,10 @@ public abstract class NZChar extends RBuiltinNode { } return RDataFactory.createLogicalVector(result, /* complete: */ keepNA && !hasNA); } + + @Specialization + protected RLogicalVector rev(@SuppressWarnings("unused") RMissing value, @SuppressWarnings("unused") boolean keepNA) { + throw RError.error(this, RError.Message.ARGUMENT_NOT_MATCH, "keepNA", "x"); + } + } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java index bb8b0830c7506c448902790900a4480c8fdd82de..e90f8a20c60ff347e62ae27981b65baf4a78a082 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java @@ -27,19 +27,32 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.InteropException; +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.java.JavaInterop; +import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.env.REnvironment; +@ImportStatic({RRuntime.class, com.oracle.truffle.api.interop.Message.class}) @RBuiltin(name = "names", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE) -public abstract class Names extends RBuiltinNode { +public abstract class Names extends RBuiltinNode.Arg1 { private final ConditionProfile hasNames = ConditionProfile.createBinaryProfile(); @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create(); @@ -64,6 +77,63 @@ public abstract class Names extends RBuiltinNode { return env.ls(true, null, false); } + @Specialization(guards = "isForeignObject(obj)") + protected Object getNames(TruffleObject obj, + @Cached("GET_SIZE.createNode()") Node getSizeNode, + @Cached("KEYS.createNode()") Node keysNode, + @Cached("READ.createNode()") Node readNode, + @Cached("IS_BOXED.createNode()") Node isBoxedNode, + @Cached("UNBOX.createNode()") Node unboxNode, + @Cached("createExecute(0).createNode()") Node callNode) { + + try { + String[] names; + try { + names = readKeys(keysNode, obj, getSizeNode, readNode, isBoxedNode, unboxNode); + } catch (UnsupportedMessageException e) { + // because it is a java function, java.util.Map (has special handling too) ... ? + return RNull.instance; + } + String[] staticNames = new String[0]; + try { + if (JavaInterop.isJavaObject(Object.class, obj)) { + TruffleObject clazz = JavaInterop.toJavaClass(obj); + staticNames = readKeys(keysNode, clazz, getSizeNode, readNode, isBoxedNode, unboxNode); + } + } catch (UnknownIdentifierException | NoSuchFieldError | UnsupportedMessageException e) { + // because it is a class ... ? + } + if (names.length == 0 && staticNames.length == 0) { + return RNull.instance; + } + String[] result = new String[names.length + staticNames.length]; + System.arraycopy(names, 0, result, 0, names.length); + System.arraycopy(staticNames, 0, result, names.length, staticNames.length); + return RDataFactory.createStringVector(result, true); + } catch (InteropException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + private String[] readKeys(Node keysNode, TruffleObject obj, Node getSizeNode, Node readNode, Node isBoxedNode, Node unboxNode) + throws UnknownIdentifierException, InteropException, UnsupportedMessageException { + TruffleObject keys = (TruffleObject) ForeignAccess.send(keysNode, obj); + if (keys != null) { + int size = (Integer) ForeignAccess.sendGetSize(getSizeNode, keys); + String[] names = new String[size]; + for (int i = 0; i < size; i++) { + Object value; + value = ForeignAccess.sendRead(readNode, keys, i); + if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) { + value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value); + } + names[i] = (String) value; + } + return names; + } + return new String[0]; + } + @Fallback protected RNull getNames(@SuppressWarnings("unused") Object operand) { return RNull.instance; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java index 276bb1ad32e42b9d1d989880e9a91e1623b1d664..6c3e1267f3eb3ea8a561ed6083059a903b88a6bc 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java @@ -50,7 +50,7 @@ public class NamespaceFunctions { } @RBuiltin(name = "getRegisteredNamespace", kind = INTERNAL, parameterNames = {"name"}, behavior = READS_STATE) - public abstract static class GetRegisteredNamespace extends RBuiltinNode { + public abstract static class GetRegisteredNamespace extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(GetRegisteredNamespace.class); @@ -79,7 +79,7 @@ public class NamespaceFunctions { } @RBuiltin(name = "isRegisteredNamespace", kind = INTERNAL, parameterNames = {"name"}, behavior = READS_STATE) - public abstract static class IsRegisteredNamespace extends RBuiltinNode { + public abstract static class IsRegisteredNamespace extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(IsRegisteredNamespace.class); @@ -108,7 +108,7 @@ public class NamespaceFunctions { } @RBuiltin(name = "isNamespaceEnv", kind = INTERNAL, parameterNames = {"env"}, behavior = PURE) - public abstract static class IsNamespaceEnv extends RBuiltinNode { + public abstract static class IsNamespaceEnv extends RBuiltinNode.Arg1 { static { Casts.noCasts(IsNamespaceEnv.class); @@ -126,7 +126,7 @@ public class NamespaceFunctions { } @RBuiltin(name = "getNamespaceRegistry", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) - public abstract static class GetNamespaceRegistry extends RBuiltinNode { + public abstract static class GetNamespaceRegistry extends RBuiltinNode.Arg0 { @Specialization protected REnvironment doGetNamespaceRegistry() { return REnvironment.getNamespaceRegistry(); @@ -134,7 +134,7 @@ public class NamespaceFunctions { } @RBuiltin(name = "registerNamespace", kind = INTERNAL, parameterNames = {"name", "env"}, behavior = MODIFIES_STATE) - public abstract static class RegisterNamespace extends RBuiltinNode { + public abstract static class RegisterNamespace extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(RegisterNamespace.class); @@ -145,7 +145,7 @@ public class NamespaceFunctions { @Specialization protected RNull registerNamespace(RAbstractStringVector name, REnvironment env) { if (REnvironment.registerNamespace(name.getDataAt(0), env) == null) { - throw RError.error(this, RError.Message.NS_ALREADY_REG); + throw error(RError.Message.NS_ALREADY_REG); } return RNull.instance; } @@ -153,7 +153,7 @@ public class NamespaceFunctions { @Specialization protected RNull registerNamespace(RSymbol nameSym, REnvironment env) { if (REnvironment.registerNamespace(nameSym.getName(), env) == null) { - throw RError.error(this, RError.Message.NS_ALREADY_REG); + throw error(RError.Message.NS_ALREADY_REG); } return RNull.instance; @@ -161,7 +161,7 @@ public class NamespaceFunctions { } @RBuiltin(name = "unregisterNamespace", kind = INTERNAL, parameterNames = {"name"}, behavior = MODIFIES_STATE) - public abstract static class UnregisterNamespace extends RBuiltinNode { + public abstract static class UnregisterNamespace extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(UnregisterNamespace.class); @@ -183,7 +183,7 @@ public class NamespaceFunctions { private void doUnregisterNamespace(String name) { Object ns = REnvironment.unregisterNamespace(name); if (ns == null) { - throw RError.error(this, RError.Message.NS_NOTREG); + throw error(RError.Message.NS_NOTREG); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java index 835eb027f59d1a5151cc2012a0e45205961daee0..a046161d57def32b221be0bfeba86bd3e748b70f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java @@ -39,7 +39,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -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; @@ -49,7 +48,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "normalizePath", kind = INTERNAL, parameterNames = {"path", "winslash", "mustwork"}, behavior = IO) -public abstract class NormalizePath extends RBuiltinNode { +public abstract class NormalizePath extends RBuiltinNode.Arg3 { private final ConditionProfile doesNotNeedToWork = ConditionProfile.createBinaryProfile(); @@ -77,20 +76,19 @@ public abstract class NormalizePath extends RBuiltinNode { if (doesNotNeedToWork.profile(mustWork == RRuntime.LOGICAL_FALSE)) { // no error or warning } else { - Object[] errorArgs; - Message msg; - if (e instanceof NoSuchFileException) { - errorArgs = new Object[]{i + 1, expandPath}; - msg = Message.NORMALIZE_PATH_NOSUCH; - } else { - errorArgs = new Object[]{e.toString()}; - msg = Message.GENERIC; - } if (mustWork == RRuntime.LOGICAL_TRUE) { - throw RError.error(this, msg, errorArgs); + if (e instanceof NoSuchFileException) { + throw error(Message.NORMALIZE_PATH_NOSUCH, i + 1, expandPath); + } else { + throw error(Message.GENERIC, e.toString()); + } } else { // NA means warning - RError.warning(this, msg, errorArgs); + if (e instanceof NoSuchFileException) { + warning(Message.NORMALIZE_PATH_NOSUCH, i + 1, expandPath); + } else { + warning(Message.GENERIC, e.toString()); + } } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NumericalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NumericalFunctions.java index 26a9bc602f80816b142a1cc48a126f4931a60ad7..c540de96876e1e0f56e5c95b70328fa1988ebc5d 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NumericalFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NumericalFunctions.java @@ -46,7 +46,7 @@ public class NumericalFunctions { * specialization, which would trigger the code generation performed by the annotation * processor. */ - public abstract static class DummyNode extends RBuiltinNode { + public abstract static class DummyNode extends RBuiltinNode.Arg1 { @Specialization protected Object dummySpec(@SuppressWarnings("unused") Object value) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java index 7d3f43e6bb2a7d14564136f1652f7e328f962c3a..3f472f67aa7dc31602afc451a53ba2d9e38f1da6 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java @@ -22,52 +22,43 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; import static com.oracle.truffle.r.runtime.RVisibility.OFF; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; -import java.util.ArrayList; - +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.FrameSlot; +import com.oracle.truffle.api.frame.FrameSlotKind; import com.oracle.truffle.api.frame.FrameSlotTypeException; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.access.ConstantNode; -import com.oracle.truffle.r.nodes.access.FrameSlotNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.runtime.RArguments; -import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RPairList; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.env.frame.RFrameSlot; -import com.oracle.truffle.r.runtime.ops.na.NAProfile; -/** - * Placeholder. {@code on.exit} is special (cf {@code .Internal} in that {@code expr} is not - * evaluated, but {@code add} is. TODO arrange for the {@code expr} be stored with the currently - * evaluating function using a new slot in {@link RArguments} and run it on function exit. - */ @RBuiltin(name = "on.exit", visibility = OFF, kind = PRIMITIVE, parameterNames = {"expr", "add"}, nonEvalArgs = 0, behavior = COMPLEX) -public abstract class OnExit extends RBuiltinNode { +public abstract class OnExit extends RBuiltinNode.Arg2 { - @Child private FrameSlotNode onExitSlot = FrameSlotNode.create(RFrameSlot.OnExit, true); + @CompilationFinal private FrameSlot onExitSlot; private final ConditionProfile addProfile = ConditionProfile.createBinaryProfile(); - private final ConditionProfile existingProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile newProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile emptyPromiseProfile = ConditionProfile.createBinaryProfile(); - private final NAProfile na = NAProfile.create(); - - private final BranchProfile invalidateProfile = BranchProfile.create(); static { Casts casts = new Casts(OnExit.class); - casts.arg("add").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); + casts.arg("add").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).mustNotBeNA().map(toBoolean()); } @Override @@ -76,42 +67,40 @@ public abstract class OnExit extends RBuiltinNode { } @Specialization - protected Object onExit(VirtualFrame frame, RPromise expr, byte add) { + protected Object onExit(VirtualFrame frame, RPromise expr, boolean add) { - if (na.isNA(add)) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "add"); + if (onExitSlot == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + onExitSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), RFrameSlot.OnExit, FrameSlotKind.Object); } // the empty (RNull.instance) expression is used to clear on.exit - boolean empty = emptyPromiseProfile.profile(expr.isDefaultArgument()); - - assert !empty || expr.getRep() instanceof ConstantNode : "only ConstantNode expected for defaulted promise"; - assert empty || !expr.isEvaluated() : "promise cannot already be evaluated"; - - ArrayList<Object> current; - FrameSlot slot = onExitSlot.executeFrameSlot(frame); - if (existingProfile.profile(onExitSlot.hasValue(frame))) { - current = getCurrentList(frame, slot); - if (addProfile.profile(!RRuntime.fromLogical(add))) { - // add is false, so clear the existing - current.clear(); - } + if (emptyPromiseProfile.profile(expr.isDefaultArgument())) { + assert expr.getRep() instanceof ConstantNode : "only ConstantNode expected for defaulted promise"; + frame.setObject(onExitSlot, RDataFactory.createPairList()); } else { - // initialize the list of exit handlers - FrameSlotChangeMonitor.setObjectAndInvalidate(frame, slot, current = new ArrayList<>(), false, invalidateProfile); - } - if (!empty) { - current.add(expr.getRep()); + assert !expr.isEvaluated() : "promise cannot already be evaluated"; + Object value; + try { + value = frame.getObject(onExitSlot); + } catch (FrameSlotTypeException e) { + throw RInternalError.shouldNotReachHere(); + } + RPairList list; + if (newProfile.profile(value == null)) { + // initialize the list of exit handlers + frame.setObject(onExitSlot, list = RDataFactory.createPairList()); + } else { + list = (RPairList) value; + if (addProfile.profile(!add)) { + // add is false, so clear the existing list + assert !list.isShared(); + list.setCdr(RNull.instance); + list.setCar(RNull.instance); + } + } + list.appendToEnd(RDataFactory.createPairList(expr.getRep())); } return RNull.instance; } - - @SuppressWarnings("unchecked") - private static ArrayList<Object> getCurrentList(VirtualFrame frame, FrameSlot slot) { - try { - return (ArrayList<Object>) frame.getObject(slot); - } catch (FrameSlotTypeException e) { - throw RInternalError.shouldNotReachHere(); - } - } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java index cc56be1bf20ed386310a29862acca11d0e86f77c..f79c0a4863229b0c2c95824a014272c403e26b2d 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java @@ -31,7 +31,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import java.util.Map; import java.util.Set; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; @@ -58,7 +57,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; public class OptionsFunctions { @RBuiltin(name = "options", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"..."}, behavior = MODIFIES_STATE) - public abstract static class Options extends RBuiltinNode { + public abstract static class Options extends RBuiltinNode.Arg1 { @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); @@ -106,8 +105,7 @@ public class OptionsFunctions { visibility.execute(frame, result.visible); return result.value; } catch (OptionsException ex) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(RError.SHOW_CALLER, ex); + throw error(ex); } } @@ -167,7 +165,7 @@ public class OptionsFunctions { names = newNames; } } else { - throw RError.error(RError.SHOW_CALLER, Message.INVALID_UNNAMED_ARGUMENT); + throw error(Message.INVALID_UNNAMED_ARGUMENT); } Object optionVal = options.getValue(optionName); data[i] = optionVal == null ? RNull.instance : optionVal; @@ -192,18 +190,18 @@ public class OptionsFunctions { } @RBuiltin(name = "getOption", kind = INTERNAL, parameterNames = "x", behavior = READS_STATE) - public abstract static class GetOption extends RBuiltinNode { + public abstract static class GetOption extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(GetOption.class); - casts.arg("x").defaultError(RError.SHOW_CALLER, RError.Message.MUST_BE_STRING, "x").mustBe(stringValue()).asStringVector().findFirst(); + casts.arg("x").defaultError(RError.Message.MUST_BE_STRING, "x").mustBe(stringValue()).asStringVector().findFirst(); } @TruffleBoundary @Specialization protected Object getOption(RAbstractStringVector x) { if (x.getLength() != 1) { - throw RError.error(RError.SHOW_CALLER, RError.Message.MUST_BE_STRING); + throw error(RError.Message.MUST_BE_STRING); } ROptions.ContextStateImpl options = RContext.getInstance().stateROptions; return options.getValue(x.getDataAt(0)); @@ -211,7 +209,7 @@ public class OptionsFunctions { @Fallback protected Object getOption(@SuppressWarnings("unused") Object x) { - throw RError.error(RError.SHOW_CALLER, RError.Message.MUST_BE_STRING); + throw error(RError.Message.MUST_BE_STRING); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java index 13d246bb06695b34f5661040159aa99ab0dc143e..3bfa03b8884869ecd48d80de293e189608fc12eb 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java @@ -40,6 +40,7 @@ import com.oracle.truffle.r.nodes.unary.CastToVectorNodeGen; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RComplex; @@ -47,7 +48,6 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.closures.RClosures; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @@ -67,6 +67,7 @@ public abstract class Order extends RPrecedenceBuiltinNode { private final BranchProfile error = BranchProfile.create(); private final ConditionProfile notRemoveNAs = ConditionProfile.createBinaryProfile(); + private final ValueProfile vectorProfile = ValueProfile.createClassProfile(); /** * For use by {@link RadixSort}. @@ -79,7 +80,8 @@ public abstract class Order extends RPrecedenceBuiltinNode { return executeOrderVector1(v, naLast, dec, false); } - private RIntVector executeOrderVector1(RAbstractVector v, byte naLast, boolean dec, boolean needsStringCollation) { + private RIntVector executeOrderVector1(RAbstractVector vIn, byte naLast, boolean dec, boolean needsStringCollation) { + RAbstractVector v = vectorProfile.profile(vIn); int n = v.getLength(); reportWork(n); @@ -137,7 +139,7 @@ public abstract class Order extends RPrecedenceBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); castVector = insert(CastToVectorNodeGen.create(false)); } - return (RAbstractVector) castVector.execute(value); + return (RAbstractVector) castVector.doCast(value); } private RAbstractVector castVector2(Object value) { @@ -145,13 +147,13 @@ public abstract class Order extends RPrecedenceBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); castVector2 = insert(CastToVectorNodeGen.create(false)); } - return (RAbstractVector) castVector2.execute(value); + return (RAbstractVector) castVector2.doCast(value); } static { Casts casts = new Casts(Order.class); casts.arg("na.last").mustBe(numericValue(), INVALID_LOGICAL, "na.last").asLogicalVector().findFirst(); - casts.arg("decreasing").mustBe(numericValue(), INVALID_LOGICAL, "decreasing").asLogicalVector().findFirst().map(toBoolean()); + casts.arg("decreasing").defaultError(INVALID_LOGICAL, "decreasing").mustBe(numericValue()).asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } private int cmp(Object v, int i, int j, boolean naLast) { @@ -170,30 +172,27 @@ public abstract class Order extends RPrecedenceBuiltinNode { @Specialization(guards = {"oneVec(args)", "isFirstIntegerPrecedence(args)"}) Object orderInt(byte naLast, boolean decreasing, RArgsValuesAndNames args) { - Object[] vectors = args.getArguments(); - RAbstractIntVector v = (RAbstractIntVector) castVector(vectors[0]); + RAbstractIntVector v = (RAbstractIntVector) castVector(args.getArgument(0)); return executeOrderVector1(v, naLast, decreasing); } @Specialization(guards = {"oneVec(args)", "isFirstDoublePrecedence(args)"}) Object orderDouble(byte naLast, boolean decreasing, RArgsValuesAndNames args) { - Object[] vectors = args.getArguments(); - RAbstractDoubleVector v = (RAbstractDoubleVector) castVector(vectors[0]); + RAbstractDoubleVector v = (RAbstractDoubleVector) castVector(args.getArgument(0)); return executeOrderVector1(v, naLast, decreasing); } @Specialization(guards = {"oneVec(args)", "isFirstLogicalPrecedence(args)"}) - Object orderLogical(byte naLast, boolean decreasing, RArgsValuesAndNames args) { - Object[] vectors = args.getArguments(); - RAbstractIntVector v = RClosures.createLogicalToIntVector((RAbstractLogicalVector) castVector(vectors[0])); + Object orderLogical(byte naLast, boolean decreasing, RArgsValuesAndNames args, + @Cached("createBinaryProfile()") ConditionProfile isNAProfile) { + RAbstractIntVector v = (RAbstractIntVector) castVector(args.getArgument(0)).castSafe(RType.Integer, isNAProfile); return executeOrderVector1(v, naLast, decreasing); } @Specialization(guards = {"oneVec(args)", "isFirstStringPrecedence(args)"}) Object orderString(byte naLast, boolean decreasing, RArgsValuesAndNames args, @Cached("create()") BranchProfile collationProfile) { - Object[] vectors = args.getArguments(); - RAbstractStringVector v = (RAbstractStringVector) castVector(vectors[0]); + RAbstractStringVector v = (RAbstractStringVector) castVector(args.getArgument(0)); int n = v.getLength(); boolean needsCollation = false; outer: for (int i = 0; i < n; i++) { @@ -213,8 +212,7 @@ public abstract class Order extends RPrecedenceBuiltinNode { @Specialization(guards = {"oneVec(args)", "isFirstComplexPrecedence( args)"}) Object orderComplex(byte naLast, boolean decreasing, RArgsValuesAndNames args) { - Object[] vectors = args.getArguments(); - RAbstractComplexVector v = (RAbstractComplexVector) castVector(vectors[0]); + RAbstractComplexVector v = (RAbstractComplexVector) castVector(args.getArgument(0)); return executeOrderVector1(v, naLast, decreasing); } @@ -233,7 +231,7 @@ public abstract class Order extends RPrecedenceBuiltinNode { case 1: return RDataFactory.createIntVectorFromScalar(1); default: - throw RError.error(RError.NO_CALLER, RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, "list", "orderVector1"); + throw error(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, "list", "orderVector1"); } } @@ -248,7 +246,7 @@ public abstract class Order extends RPrecedenceBuiltinNode { v = castVector2(vectors[i]); if (n != v.getLength()) { error.enter(); - throw RError.error(this, RError.Message.ARGUMENT_LENGTHS_DIFFER); + throw error(RError.Message.ARGUMENT_LENGTHS_DIFFER); } vectors[i] = v; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java index 55db842837ac8f3b41d9f6ae52666592b76d78dc..56edbde21bfcb951cc63a5704dfa59951b95d8a1 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java @@ -22,7 +22,6 @@ */ package com.oracle.truffle.r.nodes.builtin.base; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; @@ -30,15 +29,18 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "pmatch", kind = INTERNAL, parameterNames = {"x", "table", "nomatch", "duplicates.ok"}, behavior = PURE) -public abstract class PMatch extends RBuiltinNode { +public abstract class PMatch extends RBuiltinNode.Arg4 { private final ConditionProfile nomatchNA = ConditionProfile.createBinaryProfile(); @@ -46,12 +48,27 @@ public abstract class PMatch extends RBuiltinNode { static { Casts casts = new Casts(PMatch.class); - casts.arg("x").asStringVector(); - casts.arg("table").asStringVector(); - casts.arg("nomatch").mapNull(constant(RRuntime.INT_NA)).asIntegerVector(); + casts.arg("x").mustNotBeMissing().asStringVector(); + casts.arg("table").mustNotBeMissing().asStringVector(); + casts.arg("nomatch").mustNotBeMissing().mapIf(nullValue(), constant(RRuntime.INT_NA)).asIntegerVector().findFirst(); casts.arg("duplicates.ok").mustBe(numericValue()).asLogicalVector().findFirst().map(toBoolean()); } + @Specialization + protected RIntVector doPMatch(RNull x, RAbstractStringVector table, int nomatch, boolean duplicatesOk) { + return RDataFactory.createEmptyIntVector(); + } + + @Specialization + protected RIntVector doPMatch(RAbstractStringVector x, RNull table, int nomatch, boolean duplicatesOk) { + return RDataFactory.createEmptyIntVector(); + } + + @Specialization + protected RIntVector doPMatch(RNull x, RNull table, int nomatch, boolean duplicatesOk) { + return RDataFactory.createEmptyIntVector(); + } + @Specialization protected RIntVector doPMatch(RAbstractStringVector x, RAbstractStringVector table, int nomatch, boolean duplicatesOk) { int xl = x.getLength(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java index 0614dd2f282a2bf7b37a984e4a075a2b8d7771b5..7f2f5708175ad714b72a416c566ffb7528aa5840 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java @@ -25,8 +25,6 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalNA; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; -import static com.oracle.truffle.r.runtime.RError.NO_CALLER; -import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -68,7 +66,7 @@ import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; import com.oracle.truffle.r.runtime.ops.BinaryArithmeticFactory; import com.oracle.truffle.r.runtime.ops.na.NACheck; -public abstract class PMinMax extends RBuiltinNode { +public abstract class PMinMax extends RBuiltinNode.Arg2 { @Child private MultiElemStringHandler stringHandler; @Child private CastToVectorNode castVector; @@ -91,7 +89,7 @@ public abstract class PMinMax extends RBuiltinNode { protected static Casts createCasts(Class<? extends PMinMax> extCls) { Casts casts = new Casts(extCls); - casts.arg("na.rm").defaultError(SHOW_CALLER, Message.INVALID_VALUE, "na.rm").mustBe(numericValue()).asLogicalVector().findFirst().mustBe(logicalNA().not()).map(toBoolean()); + casts.arg("na.rm").defaultError(Message.INVALID_VALUE, "na.rm").mustBe(numericValue()).asLogicalVector().findFirst().mustBe(logicalNA().not()).map(toBoolean()); return casts; } @@ -108,7 +106,7 @@ public abstract class PMinMax extends RBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); castVector = insert(CastToVectorNodeGen.create(false)); } - return ((RAbstractVector) castVector.execute(value)).materialize(); + return ((RAbstractVector) castVector.doCast(value)).materialize(); } private CastNode getIntegerCastNode() { @@ -147,7 +145,7 @@ public abstract class PMinMax extends RBuiltinNode { return vecLength; } length = Math.max(length, vecLength); - argValues[i] = castNode.execute(v); + argValues[i] = castNode.doCast(v); } return length; } @@ -178,7 +176,7 @@ public abstract class PMinMax extends RBuiltinNode { RAbstractIntVector vec = (RAbstractIntVector) argValues[j]; na.enable(vec); if (vec.getLength() > 1 && vec.getLength() < maxLength && !warningAdded) { - RError.warning(RError.SHOW_CALLER2, RError.Message.ARG_RECYCYLED); + warning(RError.Message.ARG_RECYCYLED); warningAdded = true; } int v = vec.getDataAt(i % vec.getLength()); @@ -230,8 +228,8 @@ public abstract class PMinMax extends RBuiltinNode { @Cached("create()") CastToVectorNode castVectorX, @Cached("create()") CastToVectorNode castVectorY) { Object[] argValues = args.getArguments(); - RAbstractDoubleVector x = (RAbstractDoubleVector) castVectorX.execute(castX.execute(argValues[0])); - RAbstractDoubleVector y = (RAbstractDoubleVector) castVectorY.execute(castY.execute(argValues[1])); + RAbstractDoubleVector x = (RAbstractDoubleVector) castVectorX.doCast(castX.doCast(argValues[0])); + RAbstractDoubleVector y = (RAbstractDoubleVector) castVectorY.doCast(castY.doCast(argValues[1])); int xLength = x.getLength(); int yLength = y.getLength(); int maxLength = Math.max(xLength, yLength); @@ -241,7 +239,7 @@ public abstract class PMinMax extends RBuiltinNode { naCheckX.enable(x); naCheckY.enable(y); if ((xLength > 1 && xLength < maxLength) || (yLength > 1 && yLength < maxLength)) { - RError.warning(RError.SHOW_CALLER2, RError.Message.ARG_RECYCYLED); + warning(RError.Message.ARG_RECYCYLED); } boolean profiledNaRm = naRmProfile.profile(naRm); double[] data = new double[maxLength]; @@ -282,7 +280,7 @@ public abstract class PMinMax extends RBuiltinNode { RAbstractDoubleVector vec = (RAbstractDoubleVector) argValues[j]; na.enable(vec); if (vec.getLength() > 1 && vec.getLength() < maxLength && !warningAdded) { - RError.warning(RError.SHOW_CALLER2, RError.Message.ARG_RECYCYLED); + warning(RError.Message.ARG_RECYCYLED); warningAdded = true; } } @@ -336,7 +334,7 @@ public abstract class PMinMax extends RBuiltinNode { @SuppressWarnings("unused") @Fallback protected RRawVector pMinMaxRaw(Object naRm, Object args) { - throw RError.error(NO_CALLER, RError.Message.INVALID_INPUT_TYPE); + throw error(RError.Message.INVALID_INPUT_TYPE); } @RBuiltin(name = "pmax", kind = INTERNAL, parameterNames = {"na.rm", "..."}, behavior = PURE) @@ -424,7 +422,7 @@ public abstract class PMinMax extends RBuiltinNode { byte warningAdded = warning; RAbstractStringVector vec = (RAbstractStringVector) argValues[offset]; if (vec.getLength() > 1 && vec.getLength() < maxLength && warningAdded == RRuntime.LOGICAL_FALSE) { - RError.warning(RError.SHOW_CALLER2, RError.Message.ARG_RECYCYLED); + warning(RError.Message.ARG_RECYCYLED); warningAdded = RRuntime.LOGICAL_TRUE; } String result = vec.getDataAt(ind % vec.getLength()); @@ -451,7 +449,7 @@ public abstract class PMinMax extends RBuiltinNode { for (int i = offset + 1; i < argValues.length; i++) { vec = (RAbstractStringVector) argValues[i]; if (vec.getLength() > 1 && vec.getLength() < maxLength && warningAdded == RRuntime.LOGICAL_FALSE) { - RError.warning(this, RError.Message.ARG_RECYCYLED); + warning(RError.Message.ARG_RECYCYLED); warningAdded = RRuntime.LOGICAL_TRUE; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java index 7d68d79d72c62b7324e6ea0b4dacfce6f3a08f96..b351ea5aefea8f9e5971fd50a297d0f218430b6f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java @@ -91,7 +91,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; * On the R side, GnuR adds similar R attributes to the result, which is important for R tooling. */ @RBuiltin(name = "parse", kind = INTERNAL, parameterNames = {"conn", "n", "text", "prompt", "srcfile", "encoding"}, behavior = IO) -public abstract class Parse extends RBuiltinNode { +public abstract class Parse extends RBuiltinNode.Arg6 { @Child private CastIntegerNode castIntNode; @Child private CastStringNode castStringNode; @Child private CastToVectorNode castVectorNode; @@ -104,8 +104,8 @@ public abstract class Parse extends RBuiltinNode { Casts casts = new Casts(Parse.class); // Note: string is captured by the R wrapper and transformed to a file, other types not casts.arg("conn").defaultError(MUST_BE_STRING_OR_CONNECTION, "file").mustNotBeNull().asIntegerVector().findFirst(); - casts.arg("n").asIntegerVector().findFirst(RRuntime.INT_NA).notNA(-1); - casts.arg("text").asStringVector(); + casts.arg("n").asIntegerVector().findFirst(RRuntime.INT_NA).replaceNA(-1); + casts.arg("text").mustNotBeMissing().asStringVector(); casts.arg("prompt").asStringVector().findFirst("?"); casts.arg("encoding").mustBe(stringValue()).asStringVector().findFirst(); } @@ -121,7 +121,7 @@ public abstract class Parse extends RBuiltinNode { try (RConnection openConn = connection.forceOpen("r")) { lines = openConn.readLines(0, false, false); } catch (IOException ex) { - throw RError.error(this, RError.Message.PARSE_ERROR); + throw error(RError.Message.PARSE_ERROR); } return doParse(connection, n, lines, prompt, srcFile, encoding); } @@ -154,7 +154,7 @@ public abstract class Parse extends RBuiltinNode { } return exprs; } catch (ParseException ex) { - throw RError.error(this, RError.Message.PARSE_ERROR); + throw error(RError.Message.PARSE_ERROR); } } @@ -193,7 +193,7 @@ public abstract class Parse extends RBuiltinNode { } else { path = fileName; } - Source result = createFileSource(path, coalescedLines); + Source result = createFileSource(path, coalescedLines, false); assert result != null : "Source created from environment should not be null"; return result; } else { @@ -204,23 +204,28 @@ public abstract class Parse extends RBuiltinNode { if (srcFileText.equals("<text>")) { return Source.newBuilder(coalescedLines).name("<parse>").mimeType(RRuntime.R_APP_MIME).build(); } else { - return createFileSource(ConnectionSupport.removeFileURLPrefix(srcFileText), coalescedLines); + return createFileSource(ConnectionSupport.removeFileURLPrefix(srcFileText), coalescedLines, false); } } } private static Source createSource(RConnection conn, String coalescedLines) { // TODO check if file - String path = ConnectionSupport.getBaseConnection(conn).getSummaryDescription(); - return createFileSource(path, coalescedLines); + ConnectionSupport.BaseRConnection bconn = ConnectionSupport.getBaseConnection(conn); + String path = bconn.getSummaryDescription(); + return createFileSource(path, coalescedLines, bconn.isInternal()); } - private static Source createFileSource(String path, String chars) { + private static Source createFileSource(String path, String chars, boolean internal) { try { - return RSource.fromFileName(chars, path); + return RSource.fromFileName(chars, path, internal); } catch (URISyntaxException e) { // Note: to be compatible with GnuR we construct Source even with a malformed path - return Source.newBuilder(chars).name(path).mimeType(RRuntime.R_APP_MIME).build(); + Source.Builder<RuntimeException, RuntimeException, RuntimeException> builder = Source.newBuilder(chars).name(path).mimeType(RRuntime.R_APP_MIME); + if (internal) { + builder.internal(); + } + return builder.build(); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java index 9b682fe956c9924aa7e155f2cbf9a2cbda9e30a2..d128c387dc169ba7cfa2d328ed306a3a136d7214 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java @@ -27,7 +27,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder; import static com.oracle.truffle.r.runtime.RError.Message.NON_STRING_ARG_TO_INTERNAL_PASTE; -import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -53,7 +52,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "paste", kind = INTERNAL, parameterNames = {"", "sep", "collapse"}, behavior = PURE) -public abstract class Paste extends RBuiltinNode { +public abstract class Paste extends RBuiltinNode.Arg3 { private static final String[] ONE_EMPTY_STRING = new String[]{""}; @@ -94,11 +93,11 @@ public abstract class Paste extends RBuiltinNode { RStringVector classVec = getClassHierarchyNode().execute(result); if (hasNoClassProfile.profile(classVec == null || classVec.getLength() == 0)) { // coerce non-string result to string, i.e. do what 'as.character' would do - return getAsCharacterNode().execute(result); + return getAsCharacterNode().doCast(result); } // invoke the actual 'as.character' function (with its dispatch) ensureAsCharacterFuncNodes(); - return castAsCharacterResultNode.execute(asCharacterDispatcher.call(frame, result)); + return castAsCharacterResultNode.doCast(asCharacterDispatcher.call(frame, result)); } @Specialization @@ -223,7 +222,7 @@ public abstract class Paste extends RBuiltinNode { } if (castAsCharacterResultNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - castAsCharacterResultNode = insert(newCastBuilder().mustBe(stringValue(), SHOW_CALLER, NON_STRING_ARG_TO_INTERNAL_PASTE).buildCastNode()); + castAsCharacterResultNode = insert(newCastBuilder().mustBe(stringValue(), NON_STRING_ARG_TO_INTERNAL_PASTE).buildCastNode()); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste0.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste0.java index c00334447c68e3f0ddf4fd9a95687a6fa26a7c91..6b18011d046d0d454fad7482cfd01cfa149c53eb 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste0.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste0.java @@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.data.RList; * efficient. */ @RBuiltin(name = "paste0", kind = INTERNAL, parameterNames = {"list", "collapse"}, behavior = PURE) -public abstract class Paste0 extends RBuiltinNode { +public abstract class Paste0 extends RBuiltinNode.Arg2 { @Child private Paste pasteNode = PasteNodeGen.create(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PathExpand.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PathExpand.java index fe07eed30f65a47f88c8d9eb8c39e3d4ced3f71c..280c627acb8b4b5b4a5453530f47ecde37d92a14 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PathExpand.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PathExpand.java @@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "path.expand", kind = INTERNAL, parameterNames = "path", behavior = IO) -public abstract class PathExpand extends RBuiltinNode { +public abstract class PathExpand extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(PathExpand.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java index aa7eaefcc74362e768a04c08765ff762f4df2445..f44ff63f51a6af10e960ba1fefe0eef72d278c69 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java @@ -22,6 +22,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.runtime.PrettyIntevals; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -31,7 +32,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; @RBuiltin(name = "pretty", kind = INTERNAL, parameterNames = {"l", "u", "n", "min.n", "shrink.sml", "hi", "eps.correct"}, behavior = PURE) -public abstract class Pretty extends RBuiltinNode { +public abstract class Pretty extends RBuiltinNode.Arg7 { private static final RStringVector NAMES = RDataFactory.createStringVector(new String[]{"l", "u", "n"}, RDataFactory.COMPLETE_VECTOR); @@ -39,172 +40,34 @@ public abstract class Pretty extends RBuiltinNode { Casts casts = new Casts(Pretty.class); casts.arg("l").asDoubleVector().findFirst().mustBe(isFinite()); casts.arg("u").asDoubleVector().findFirst().mustBe(isFinite()); - casts.arg("n").asIntegerVector().findFirst().notNA().mustBe(gte0()); - casts.arg("min.n").asIntegerVector().findFirst().notNA().mustBe(gte0()); + casts.arg("n").asIntegerVector().findFirst().mustNotBeNA().mustBe(gte0()); + casts.arg("min.n").asIntegerVector().findFirst().mustNotBeNA().mustBe(gte0()); casts.arg("shrink.sml").asDoubleVector().findFirst().mustBe(and(isFinite(), gt(0.0))); casts.arg("hi").asDoubleVector().mustBe(size(2)); - casts.arg("eps.correct").defaultError(RError.Message.GENERIC, "'eps.correct' must be 0, 1, or 2").asIntegerVector().findFirst().notNA().mustBe(and(gte0(), lte(2))); + casts.arg("eps.correct").defaultError(RError.Message.GENERIC, "'eps.correct' must be 0, 1, or 2").asIntegerVector().findFirst().mustNotBeNA().mustBe(and(gte0(), lte(2))); } + public abstract RList execute(double l, double u, int n, int minN, double shrinkSml, RAbstractDoubleVector hi, int epsCorrect); + @Specialization protected RList pretty(double l, double u, int n, int minN, double shrinkSml, RAbstractDoubleVector hi, int epsCorrect) { double hi0 = hi.getDataAt(0); double hi1 = hi.getDataAt(1); if (!RRuntime.isFinite(hi0) || hi0 < 0.0) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "high.u.bias"); + throw error(RError.Message.INVALID_ARGUMENT, "high.u.bias"); } if (!RRuntime.isFinite(hi1) || hi1 < 0.0) { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "u5.bias"); + throw error(RError.Message.INVALID_ARGUMENT, "u5.bias"); } double[] lo = new double[]{l}; double[] up = new double[]{u}; int[] ndiv = new int[]{n}; - rPretty(lo, up, ndiv, minN, shrinkSml, hi.materialize().getDataWithoutCopying(), epsCorrect, true); + PrettyIntevals.pretty(getErrorContext(), lo, up, ndiv, minN, shrinkSml, hi.materialize().getDataWithoutCopying(), epsCorrect, true); Object[] data = new Object[3]; data[0] = lo[0]; data[1] = up[0]; data[2] = ndiv[0]; return RDataFactory.createList(data, NAMES); } - - double rPretty(double[] lo, double[] up, int[] ndiv, int minN, - double shrinkSml, double[] highUFact, - int epsCorrection, boolean returnBounds) { - /* - * From version 0.65 on, we had rounding_eps := 1e-5, before, r..eps = 0 1e-7 is consistent - * with seq.default() - */ - double roundingEps = 1e-7; - - double h = highUFact[0]; - double h5 = highUFact[1]; - - double dx; - double cell; - double unit; - double base; - double uu; - double ns; - double nu; - int k; - boolean iSmall; - - dx = up[0] - lo[0]; - /* cell := "scale" here */ - if (dx == 0 && up[0] == 0) { /* up == lo == 0 */ - cell = 1; - iSmall = true; - } else { - cell = Math.max(Math.abs(lo[0]), Math.abs(up[0])); - /* uu = upper bound on cell/unit */ - // uu = (1 + (h5 >= 1.5 * h + .5)) ? 1 / (1 + h) : 1.5 / (1 + h5); - // How can above expression ever be zero? - uu = 1 / (1 + h); - /* added times 3, as several calculations here */ - iSmall = dx < cell * uu * Math.max(1, ndiv[0]) * RRuntime.EPSILON * 3; - } - - /* OLD: cell = FLT_EPSILON+ dx / ndiv[0]; FLT_EPSILON = 1.192e-07 */ - if (iSmall) { - if (cell > 10) { - cell = 9 + cell / 10; - } - cell *= shrinkSml; - if (minN > 1) { - cell /= minN; - } - } else { - cell = dx; - if (ndiv[0] > 1) { - cell /= ndiv[0]; - } - } - - if (cell < 20 * Double.MIN_VALUE) { - RError.warning(this, RError.Message.GENERIC, "Internal(pretty()): very small range.. corrected"); - cell = 20 * Double.MIN_VALUE; - } else if (cell * 10 > Double.MAX_VALUE) { - RError.warning(this, RError.Message.GENERIC, "Internal(pretty()): very large range.. corrected"); - cell = .1 * Double.MAX_VALUE; - } - /* - * NB: the power can be negative and this relies on exact calculation, which glibc's exp10 - * does not achieve - */ - base = Math.pow(10.0, Math.floor(Math.log10(cell))); /* base <= cell < 10*base */ - - /* - * unit : from { 1,2,5,10 } * base such that |u - cell| is small, favoring larger (if h > 1, - * else smaller) u values; favor '5' more than '2' if h5 > h (default h5 = .5 + 1.5 h) - */ - unit = base; - if ((uu = 2 * base) - cell < h * (cell - unit)) { - unit = uu; - if ((uu = 5 * base) - cell < h5 * (cell - unit)) { - unit = uu; - if ((uu = 10 * base) - cell < h * (cell - unit)) { - unit = uu; - } - } - } - /* - * Result: c := cell, u := unit, b := base c in [ 1, (2+ h) /(1+h) ] b ==> u= b c in ( (2+ - * h)/(1+h), (5+2h5)/(1+h5)] b ==> u= 2b c in ( (5+2h)/(1+h), (10+5h) /(1+h) ] b ==> u= 5b c - * in ((10+5h)/(1+h), 10 ) b ==> u=10b - * - * ===> 2/5 *(2+h)/(1+h) <= c/u <= (2+h)/(1+h) - */ - - ns = Math.floor(lo[0] / unit + roundingEps); - nu = Math.ceil(up[0] / unit - roundingEps); - if (epsCorrection != 0 && (epsCorrection > 1 || !iSmall)) { - if (lo[0] != 0.) { - lo[0] *= (1 - RRuntime.EPSILON); - } else { - lo[0] = -Double.MIN_VALUE; - } - if (up[0] != 0.) { - up[0] *= (1 + RRuntime.EPSILON); - } else { - up[0] = +Double.MIN_VALUE; - } - } - - while (ns * unit > lo[0] + roundingEps * unit) { - ns--; - } - - while (nu * unit < up[0] - roundingEps * unit) { - nu++; - } - - k = (int) (0.5 + nu - ns); - if (k < minN) { - /* ensure that nu - ns == min_n */ - k = minN - k; - if (ns >= 0.) { - nu += k / 2; - ns -= k / 2 + k % 2; /* ==> nu-ns = old(nu-ns) + min_n -k = min_n */ - } else { - ns -= k / 2; - nu += k / 2 + k % 2; - } - ndiv[0] = minN; - } else { - ndiv[0] = k; - } - if (returnBounds) { /* if()'s to ensure that result covers original range */ - if (ns * unit < lo[0]) { - lo[0] = ns * unit; - } - if (nu * unit > up[0]) { - up[0] = nu * unit; - } - } else { - lo[0] = ns; - up[0] = nu; - } - return unit; - } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java index 0a6d792c11e56c01789697c7799bcb810f7efee4..3dcea15589c1caa75e692575d74107077b8c9f2d 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java @@ -30,7 +30,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; @@ -40,9 +39,7 @@ import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RFunction; @RBuiltin(name = ".Primitive", kind = PRIMITIVE, parameterNames = "name", behavior = PURE) -public abstract class Primitive extends RBuiltinNode { - - private final BranchProfile errorProfile = BranchProfile.create(); +public abstract class Primitive extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(Primitive.class); @@ -66,8 +63,7 @@ public abstract class Primitive extends RBuiltinNode { protected RFunction lookup(String name) { RFunction function = RContext.lookupBuiltin(name); if (function == null || function.getRBuiltin() != null && function.getRBuiltin().getKind() != RBuiltinKind.PRIMITIVE) { - errorProfile.enter(); - throw RError.error(this, RError.Message.NO_SUCH_PRIMITIVE, name); + throw error(RError.Message.NO_SUCH_PRIMITIVE, name); } return function; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java index 9abaf902ac3f6f2f215952fbd29178e06c95035c..873b10c3c1e1777b846da88ff8d5d53e37c9ea5f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java @@ -47,13 +47,12 @@ import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RString; import com.oracle.truffle.r.runtime.data.RTypedValue; public class PrintFunctions { @RBuiltin(name = "print.default", visibility = OFF, kind = INTERNAL, parameterNames = {"x", "digits", "quote", "na.print", "print.gap", "right", "max", "useSource", "noOpt"}, behavior = IO) - public abstract static class PrintDefault extends RBuiltinNode { + public abstract static class PrintDefault extends RBuiltinNode.Arg9 { @Child private GetClassAttributeNode getClassNode = GetClassAttributeNode.create(); @@ -63,19 +62,19 @@ public class PrintFunctions { Casts casts = new Casts(PrintDefault.class); casts.arg("digits").allowNull().asIntegerVector().findFirst().mustBe(notIntNA()).mustBe(gte(Format.R_MIN_DIGITS_OPT).and(lte(Format.R_MAX_DIGITS_OPT))); - casts.arg("quote").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("quote").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); casts.arg("na.print").defaultError(RError.Message.INVALID_NA_PRINT_SPEC).allowNull().mustBe(stringValue()).asStringVector().findFirst(); casts.arg("print.gap").defaultError(RError.Message.GAP_MUST_BE_NON_NEGATIVE).allowNull().asIntegerVector().findFirst().mustBe(notIntNA()).mustBe(gte(0)); - casts.arg("right").defaultError(RError.Message.INVALID_ARGUMENT, "right").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("right").defaultError(RError.Message.INVALID_ARGUMENT, "right").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); casts.arg("max").allowNull().asIntegerVector().findFirst().mustBe(notIntNA()).mustBe(gte(0)); - casts.arg("useSource").defaultError(RError.Message.INVALID_ARGUMENT, "useSource").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("useSource").defaultError(RError.Message.INVALID_ARGUMENT, "useSource").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); - casts.arg("noOpt").defaultError(RError.Message.GENERIC, "invalid 'tryS4' internal argument").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("noOpt").defaultError(RError.Message.GENERIC, "invalid 'tryS4' internal argument").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } @Specialization(guards = "!isS4(o)") @@ -107,7 +106,7 @@ public class PrintFunctions { } @RBuiltin(name = "print.function", visibility = OFF, kind = INTERNAL, parameterNames = {"x", "useSource", "..."}, behavior = IO) - public abstract static class PrintFunction extends RBuiltinNode { + public abstract static class PrintFunction extends RBuiltinNode.Arg3 { @Child private ValuePrinterNode valuePrinter = new ValuePrinterNode(); @@ -120,7 +119,7 @@ public class PrintFunctions { @Specialization protected RFunction printFunction(RFunction x, boolean useSource, @SuppressWarnings("unused") RArgsValuesAndNames extra) { - valuePrinter.execute(x, PrintParameters.getDefaultDigits(), true, RString.valueOf(RRuntime.STRING_NA), 1, false, PrintParameters.getDefaultMaxPrint(), useSource, false); + valuePrinter.execute(x, PrintParameters.getDefaultDigits(), true, RRuntime.STRING_NA, 1, false, PrintParameters.getDefaultMaxPrint(), useSource, false); return x; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.java index 24496e3ae2d465157530b90cb0d3a2f76122ff08..2492d86ee9d3acec7bd559b9879621153f621409 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.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 @@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RStringVector; @RBuiltin(name = "proc.time", kind = PRIMITIVE, parameterNames = {}, behavior = IO) -public abstract class ProcTime extends RBuiltinNode { +public abstract class ProcTime extends RBuiltinNode.Arg0 { private static final String[] NAMES = new String[]{"user.self", "sys.self", "elapsed", "user.child", "sys.child"}; private static final RStringVector PROC_TIME_CLASS = RDataFactory.createStringVectorFromScalar("proc_time"); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java index 132a9648895544e951e370763858a77e5063bd4a..cc8bb51840f6ba32e8df0069bd2637e80d157460 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java @@ -15,12 +15,17 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RComplex; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @@ -28,7 +33,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; @RBuiltin(name = "prod", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE) -public abstract class Prod extends RBuiltinNode { +public abstract class Prod extends RBuiltinNode.Arg2 { // TODO: handle multiple arguments, handle na.rm @@ -49,48 +54,105 @@ public abstract class Prod extends RBuiltinNode { @Specialization protected Object prod(RArgsValuesAndNames args) { + int argsLen = args.getLength(); + if (argsLen == 0) { + return 1d; + } if (prodRecursive == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); prodRecursive = insert(ProdNodeGen.create()); } - // TODO: eventually handle multiple vectors properly - return prodRecursive.executeObject(args.getArgument(0)); + Object ret = prodRecursive.executeObject(args.getArgument(0)); + if (argsLen != 1) { + double prodReal; + double prodImg; + boolean complex; + if (ret instanceof RComplex) { + RComplex c = (RComplex) ret; + prodReal = c.getRealPart(); + prodImg = c.getImaginaryPart(); + complex = true; + } else { + prodReal = (Double) ret; + prodImg = 0d; + complex = false; + } + for (int i = 1; i < argsLen; i++) { + Object aProd = prodRecursive.executeObject(args.getArgument(i)); + double aProdReal; + double aProdImg; + if (aProd instanceof RComplex) { + RComplex c = (RComplex) aProd; + aProdReal = c.getRealPart(); + aProdImg = c.getImaginaryPart(); + complex = true; + } else { + aProdReal = (Double) aProd; + aProdImg = 0d; + } + if (complex) { + RComplex c = prod.op(prodReal, prodImg, aProdReal, aProdImg); + prodReal = c.getRealPart(); + prodImg = c.getImaginaryPart(); + } else { + prodReal = prod.op(prodReal, aProdReal); + } + } + ret = complex ? RComplex.valueOf(prodReal, prodImg) : prodReal; + } + return ret; } + private final ValueProfile intVecProfile = ValueProfile.createClassProfile(); + @Specialization protected double prod(RAbstractDoubleVector x) { - double product = x.getDataAt(0); - for (int k = 1; k < x.getLength(); k++) { - product = prod.op(product, x.getDataAt(k)); + RAbstractDoubleVector profiledVec = intVecProfile.profile(x); + double product = profiledVec.getDataAt(0); + for (int k = 1; k < profiledVec.getLength(); k++) { + product = prod.op(product, profiledVec.getDataAt(k)); } return product; } @Specialization protected double prod(RAbstractIntVector x) { - double product = x.getDataAt(0); - for (int k = 1; k < x.getLength(); k++) { - product = prod.op(product, x.getDataAt(k)); + RAbstractIntVector profiledVec = intVecProfile.profile(x); + double product = profiledVec.getDataAt(0); + for (int k = 1; k < profiledVec.getLength(); k++) { + product = prod.op(product, profiledVec.getDataAt(k)); } return product; } @Specialization protected double prod(RAbstractLogicalVector x) { - double product = x.getDataAt(0); - for (int k = 1; k < x.getLength(); k++) { - product = prod.op(product, x.getDataAt(k)); + RAbstractLogicalVector profiledVec = intVecProfile.profile(x); + double product = profiledVec.getDataAt(0); + for (int k = 1; k < profiledVec.getLength(); k++) { + product = prod.op(product, profiledVec.getDataAt(k)); } return product; } @Specialization protected RComplex prod(RAbstractComplexVector x) { - RComplex product = x.getDataAt(0); - for (int k = 1; k < x.getLength(); k++) { - RComplex a = x.getDataAt(k); + RAbstractComplexVector profiledVec = intVecProfile.profile(x); + RComplex product = profiledVec.getDataAt(0); + for (int k = 1; k < profiledVec.getLength(); k++) { + RComplex a = profiledVec.getDataAt(k); product = prod.op(product.getRealPart(), product.getImaginaryPart(), a.getRealPart(), a.getImaginaryPart()); } return product; } + + @Specialization + protected double prod(@SuppressWarnings("unused") RNull n) { + return 1d; + } + + @Fallback + protected Object prod(Object o) { + throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, ((RTypedValue) RRuntime.asAbstractVector(o)).getRType().getName()); + } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java index 37bba1bf203b24d61c73dd5690a30c34f7cd44d6..c88f58c48a9703b7707d9aa61feb523fa61105c2 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java @@ -35,6 +35,7 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.unary.CastNode; @@ -48,7 +49,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; -public abstract class Quantifier extends RBuiltinNode { +public abstract class Quantifier extends RBuiltinNode.Arg2 { protected static final int MAX_CACHED_LENGTH = 10; private final NACheck naCheck = NACheck.create(); @@ -62,13 +63,14 @@ public abstract class Quantifier extends RBuiltinNode { private final ValueProfile profile = ValueProfile.createClassProfile(); @Child private CastNode next; - ProfileCastNode(CastNode next) { - this.next = next; + ProfileCastNode() { + this.next = newCastBuilder().allowNull().shouldBe(integerValue().or(logicalValue()).or(instanceOf(RAbstractVector.class).and(size(0))), + RError.Message.COERCING_ARGUMENT, typeName(), "logical").asLogicalVector().buildCastNode(); } @Override public Object execute(Object value) { - return profile.profile(next.execute(value)); + return profile.profile(next.doCast(value)); } } @@ -79,17 +81,12 @@ public abstract class Quantifier extends RBuiltinNode { protected static Casts createCasts(Class<? extends Quantifier> extCls) { Casts casts = new Casts(extCls); - casts.arg("na.rm").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean()); + casts.arg("na.rm").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); return casts; } private void createArgCast(int index) { - // @formatter:off - argCastNodes[index] = insert(new ProfileCastNode(newCastBuilder().allowNull(). - shouldBe(integerValue().or(logicalValue()).or(instanceOf(RAbstractVector.class).and(size(0))), - RError.Message.COERCING_ARGUMENT, typeName(), "logical"). - asLogicalVector().buildCastNode())); - // @formatter:on + argCastNodes[index] = insert(new ProfileCastNode()); } protected boolean emptyVectorResult() { @@ -126,8 +123,9 @@ public abstract class Quantifier extends RBuiltinNode { } @Specialization(replaces = "opCachedLength") - protected byte op(RArgsValuesAndNames args, boolean naRm) { - boolean profiledNaRm = naRm; + protected byte op(RArgsValuesAndNames args, boolean naRm, + @Cached("createBinaryProfile()") ConditionProfile naRmProfile) { + boolean profiledNaRm = naRmProfile.profile(naRm); byte result = RRuntime.asLogical(emptyVectorResult()); for (Object argValue : args.getArguments()) { @@ -148,7 +146,7 @@ public abstract class Quantifier extends RBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); createArgCast(index); } - Object castValue = argCastNodes[index].execute(argValue); + Object castValue = argCastNodes[index].doCast(argValue); if (castValue instanceof RAbstractLogicalVector) { RAbstractLogicalVector vector = (RAbstractLogicalVector) castValue; naCheck.enable(vector); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java index 4a3d93122cab344c22ab3bff41cd344f2787faa5..9d9aa1803a2339befd7fb842563c88c81b026a7b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java @@ -31,7 +31,7 @@ import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RNull; @RBuiltin(name = "quit", visibility = OFF, kind = INTERNAL, parameterNames = {"save", "status", "runLast"}, behavior = COMPLEX) -public abstract class Quit extends RBuiltinNode { +public abstract class Quit extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(Quit.class); @@ -46,7 +46,7 @@ public abstract class Quit extends RBuiltinNode { return SA_TYPE.fromString(save); } } - throw RError.error(this, RError.Message.QUIT_SAVE); + throw error(RError.Message.QUIT_SAVE); } @Specialization @@ -54,19 +54,19 @@ public abstract class Quit extends RBuiltinNode { protected Object doQuit(String save, final int status, final byte runLastIn) { byte runLast = runLastIn; if (RContext.getInstance().stateInstrumentation.getBrowserState().inBrowser()) { - RError.warning(this, RError.Message.BROWSER_QUIT); + warning(RError.Message.BROWSER_QUIT); return RNull.instance; } RStartParams.SA_TYPE ask = checkSaveValue(save); if (ask == SA_TYPE.SAVEASK && !RContext.getInstance().getConsoleHandler().isInteractive()) { - RError.warning(this, RError.Message.QUIT_ASK_INTERACTIVE); + warning(RError.Message.QUIT_ASK_INTERACTIVE); } if (status == RRuntime.INT_NA) { - RError.warning(this, RError.Message.QUIT_INVALID_STATUS); + warning(RError.Message.QUIT_INVALID_STATUS); runLast = RRuntime.LOGICAL_FALSE; } if (runLast == RRuntime.LOGICAL_NA) { - RError.warning(this, RError.Message.QUIT_INVALID_RUNLAST); + warning(RError.Message.QUIT_INVALID_RUNLAST); runLast = RRuntime.LOGICAL_FALSE; } RCleanUp.cleanUp(ask, status, RRuntime.fromLogical(runLast)); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java index 98620c384f3b17e826ea6058afa2a3c7ace3a036..9daaa44d052386fb4e39e265e6f5c2416a3edfe2 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java @@ -31,12 +31,14 @@ import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.RASTUtils; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RPromise.Closure; import com.oracle.truffle.r.runtime.data.RShareable; +import com.oracle.truffle.r.runtime.data.RSymbol; @RBuiltin(name = "quote", nonEvalArgs = 0, kind = PRIMITIVE, parameterNames = {"expr"}, behavior = PURE) -public abstract class Quote extends RBuiltinNode { +public abstract class Quote extends RBuiltinNode.Arg1 { protected static final int LIMIT = 3; @@ -76,4 +78,9 @@ public abstract class Quote extends RBuiltinNode { protected Object quote(RPromise expr) { return createLanguage(expr.getClosure()); } + + @Specialization + protected Object quote(@SuppressWarnings("unused") RMissing expr) { + return RSymbol.MISSING; + } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/do.call.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/do.call.R new file mode 100644 index 0000000000000000000000000000000000000000..ffbeb252c5d9d3b13704fd9859bd653c9286a33a --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/do.call.R @@ -0,0 +1,7 @@ +# 'do.call' needs to be a function for S4 but we do not use 'enquote' for performance reasons +do.call <- function(what, args, quote = FALSE, envir = parent.frame()) +{ + if (!is.list(args)) + stop("second argument must be a list") + .Internal(.fastr.do.call(what, args, quote, envir)) +} \ No newline at end of file diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java index 315f03279d911c82020ff0608d5c320dbc28f618..146b768b00d6e5e06d36ed4f3d07fb6438f9ec89 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java @@ -26,7 +26,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.anyValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; -import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ARGUMENT; import static com.oracle.truffle.r.runtime.RError.Message.INVALID_NORMAL_TYPE_IN_RGNKIND; import static com.oracle.truffle.r.runtime.RError.Message.SEED_NOT_VALID_INT; @@ -36,8 +35,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.MODIFIES_STATE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.dsl.TypeSystemReference; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError.Message; @@ -48,16 +45,15 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.rng.RRNG; public class RNGFunctions { - @TypeSystemReference(EmptyTypeSystemFlatLayout.class) @RBuiltin(name = "set.seed", visibility = OFF, kind = INTERNAL, parameterNames = {"seed", "kind", "normal.kind"}, behavior = MODIFIES_STATE) - public abstract static class SetSeed extends RBuiltinNode { + public abstract static class SetSeed extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(SetSeed.class); - casts.arg("seed").allowNull().mustBe(numericValue(), SHOW_CALLER, SEED_NOT_VALID_INT).asIntegerVector().findFirst(); + casts.arg("seed").allowNull().mustBe(numericValue(), SEED_NOT_VALID_INT).asIntegerVector().findFirst(); CastsHelper.kindInteger(casts, "kind", INVALID_ARGUMENT, "kind"); // TODO: implement normal.kind specializations with String - casts.arg("normal.kind").allowNull().mustBe(anyValue().not(), UNIMPLEMENTED_TYPE_IN_FUNCTION, "String", "set.seed").mustBe(stringValue(), SHOW_CALLER, INVALID_NORMAL_TYPE_IN_RGNKIND); + casts.arg("normal.kind").allowNull().mustBe(anyValue().not(), UNIMPLEMENTED_TYPE_IN_FUNCTION, "String", "set.seed").mustBe(stringValue(), INVALID_NORMAL_TYPE_IN_RGNKIND); } @SuppressWarnings("unused") @@ -79,9 +75,8 @@ public class RNGFunctions { } } - @TypeSystemReference(EmptyTypeSystemFlatLayout.class) @RBuiltin(name = "RNGkind", kind = INTERNAL, parameterNames = {"kind", "normkind"}, behavior = MODIFIES_STATE) - public abstract static class RNGkind extends RBuiltinNode { + public abstract static class RNGkind extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(RNGkind.class); @@ -104,7 +99,7 @@ public class RNGFunctions { private static final class CastsHelper { public static void kindInteger(Casts casts, String name, Message error, Object... messageArgs) { - casts.arg(name).mapNull(constant(RRNG.NO_KIND_CHANGE)).mustBe(numericValue(), SHOW_CALLER, error, messageArgs).asIntegerVector().findFirst(); + casts.arg(name).mapNull(constant(RRNG.NO_KIND_CHANGE)).mustBe(numericValue(), error, messageArgs).asIntegerVector().findFirst(); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RVersion.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RVersion.java index 53e566ab53d8bf98d87755dc076fcfbefb984e12..5deeb4662eddf0329a88478afd547eee3a3fcdbf 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RVersion.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RVersion.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 @@ -33,7 +33,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; @RBuiltin(name = "Version", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) -public abstract class RVersion extends RBuiltinNode { +public abstract class RVersion extends RBuiltinNode.Arg0 { @Specialization @TruffleBoundary diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Range.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Range.java index 72ab6ad5c7e4227fd90998c13f5f7ed3825a0e0f..f80721c116078771e8f6c3d76fc83e37d56d96b1 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Range.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Range.java @@ -42,7 +42,7 @@ import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; @RBuiltin(name = "range", kind = PRIMITIVE, parameterNames = {"...", "na.rm", "finite"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE) -public abstract class Range extends RBuiltinNode { +public abstract class Range extends RBuiltinNode.Arg3 { private static final ReduceSemantics minSemantics = new ReduceSemantics(RRuntime.INT_MAX_VALUE, Double.POSITIVE_INFINITY, false, RError.Message.NO_NONMISSING_MIN, RError.Message.NO_NONMISSING_MIN_NA, false, true); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java index 16f4d02288df99cd558c9ce7b8f13234589980ba..c15016ffb9bde4c2dc0f275de2ff1e4e00574c51 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java @@ -20,8 +20,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.rawValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; -import static com.oracle.truffle.r.runtime.RError.NO_CALLER; -import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; import static com.oracle.truffle.r.runtime.RError.Message.INVALID_TIES_FOR_RANK; import static com.oracle.truffle.r.runtime.RError.Message.INVALID_VALUE; import static com.oracle.truffle.r.runtime.RError.Message.RANK_LARGE_N; @@ -32,22 +30,24 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import java.util.function.Function; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.OrderNodeGen.CmpNodeGen; import com.oracle.truffle.r.nodes.builtin.base.OrderNodeGen.OrderVector1NodeGen; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RIntVector; -import com.oracle.truffle.r.runtime.data.closures.RClosures; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "rank", kind = INTERNAL, parameterNames = {"x", "len", "ties.method"}, behavior = PURE) -public abstract class Rank extends RBuiltinNode { +public abstract class Rank extends RBuiltinNode.Arg3 { @Child private Order.OrderVector1Node orderVector1Node; @Child private Order.CmpNode orderCmpNode; @@ -64,14 +64,14 @@ public abstract class Rank extends RBuiltinNode { static { Casts casts = new Casts(Rank.class); Function<Object, Object> typeFunc = x -> x.getClass().getSimpleName(); - casts.arg("x").mustBe(abstractVectorValue(), SHOW_CALLER, UNIMPLEMENTED_TYPE_IN_GREATER, typeFunc).mustBe(not(rawValue()), SHOW_CALLER, RError.Message.RAW_SORT); + casts.arg("x").mustBe(abstractVectorValue(), UNIMPLEMENTED_TYPE_IN_GREATER, typeFunc).mustBe(not(rawValue()), RError.Message.RAW_SORT); // Note: in the case of no long vector support, when given anything but integer as n, GnuR // behaves as if n=1, // we allow ourselves to be bit inconsistent with GnuR in that. - casts.arg("len").defaultError(NO_CALLER, INVALID_VALUE, "length(xx)").mustBe(numericValue()).asIntegerVector().mustBe(notEmpty()).findFirst().mustBe(intNA().not().and(gte0())); + casts.arg("len").defaultError(INVALID_VALUE, "length(xx)").mustBe(numericValue()).asIntegerVector().mustBe(notEmpty()).findFirst().mustBe(intNA().not().and(gte0())); // Note: we parse ties.methods in the Specialization anyway, so the validation of the value // is there - casts.arg("ties.method").defaultError(NO_CALLER, INVALID_TIES_FOR_RANK).mustBe(stringValue()).asStringVector().findFirst(); + casts.arg("ties.method").defaultError(INVALID_TIES_FOR_RANK).mustBe(stringValue()).asStringVector().findFirst(); } private Order.OrderVector1Node initOrderVector1() { @@ -91,12 +91,13 @@ public abstract class Rank extends RBuiltinNode { } @Specialization - protected Object rank(RAbstractVector xa, int inN, String tiesMethod) { + protected Object rank(RAbstractVector xa, int inN, String tiesMethod, + @Cached("createBinaryProfile()") ConditionProfile isNAProfile) { int n = inN; if (n > xa.getLength()) { errorProfile.enter(); n = xa.getLength(); - RError.warning(SHOW_CALLER, RANK_LARGE_N); + warning(RANK_LARGE_N); } TiesKind tiesKind = getTiesKind(tiesMethod); @@ -112,7 +113,7 @@ public abstract class Rank extends RBuiltinNode { indx[i] = i; } RIntVector indxVec = RDataFactory.createIntVector(indx, RDataFactory.COMPLETE_VECTOR); - RAbstractVector x = xa instanceof RAbstractLogicalVector ? RClosures.createLogicalToIntVector((RAbstractLogicalVector) xa) : xa; + RAbstractVector x = xa instanceof RAbstractLogicalVector ? xa.castSafe(RType.Integer, isNAProfile) : xa; initOrderVector1().execute(indxVec, x, RRuntime.LOGICAL_TRUE, false, rho); initOrderCmp(); int j; @@ -156,7 +157,7 @@ public abstract class Rank extends RBuiltinNode { return TiesKind.MIN; default: errorProfile.enter(); - throw RError.error(NO_CALLER, RError.Message.GENERIC, "invalid ties.method for rank() [should never happen]"); + throw error(RError.Message.GENERIC, "invalid ties.method for rank() [should never happen]"); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java index 4278530d54041bc9d62b0e24d0dbe9e542fcd48b..f1fc024fe923095495b1959baa8b14c0fe235187 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java @@ -50,7 +50,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; public class RawFunctions { @RBuiltin(name = "charToRaw", kind = INTERNAL, parameterNames = "x", behavior = PURE) - public abstract static class CharToRaw extends RBuiltinNode { + public abstract static class CharToRaw extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(CharToRaw.class); @@ -60,7 +60,7 @@ public class RawFunctions { @Specialization protected RRawVector charToRaw(RAbstractStringVector x) { if (x.getLength() > 1) { - RError.warning(this, RError.Message.ARG_SHOULD_BE_CHARACTER_VECTOR_LENGTH_ONE); + warning(RError.Message.ARG_SHOULD_BE_CHARACTER_VECTOR_LENGTH_ONE); } String s = x.getDataAt(0); byte[] data = new byte[s.length()]; @@ -72,12 +72,12 @@ public class RawFunctions { } @RBuiltin(name = "rawToChar", kind = INTERNAL, parameterNames = {"x", "multiple"}, behavior = PURE) - public abstract static class RawToChar extends RBuiltinNode { + public abstract static class RawToChar extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(RawToChar.class); - casts.arg("x").mustBe(instanceOf(RAbstractRawVector.class), RError.SHOW_CALLER, RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x"); - casts.arg("multiple").defaultError(RError.Message.INVALID_LOGICAL).asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("x").mustBe(instanceOf(RAbstractRawVector.class), RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x"); + casts.arg("multiple").defaultError(RError.Message.INVALID_LOGICAL).asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } @Specialization @@ -106,12 +106,12 @@ public class RawFunctions { } @RBuiltin(name = "rawShift", kind = INTERNAL, parameterNames = {"x", "n"}, behavior = PURE) - public abstract static class RawShift extends RBuiltinNode { + public abstract static class RawShift extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(RawShift.class); - casts.arg("x").mustBe(instanceOf(RAbstractRawVector.class), RError.SHOW_CALLER, RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x"); - casts.arg("n").defaultError(RError.Message.MUST_BE_SMALL_INT, "shift").asIntegerVector().findFirst().notNA().mustBe(gte(-8).and(lte(8))); + casts.arg("x").mustBe(instanceOf(RAbstractRawVector.class), RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x"); + casts.arg("n").defaultError(RError.Message.MUST_BE_SMALL_INT, "shift").asIntegerVector().findFirst().mustNotBeNA().mustBe(gte(-8).and(lte(8))); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawToBits.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawToBits.java index 538a0d8c685b99f55f14cc98478b740dfb422e7e..3afe3566f550717f1ebf1ee311c4e129a4659027 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawToBits.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawToBits.java @@ -34,12 +34,11 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; @RBuiltin(name = "rawToBits", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) -public abstract class RawToBits extends RBuiltinNode { +public abstract class RawToBits extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(RawToBits.class); - casts.arg("x").mustNotBeNull(RError.SHOW_CALLER, RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x").mustBe(Predef.rawValue(), RError.SHOW_CALLER, - RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x"); + casts.arg("x").mustNotBeNull(RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x").mustBe(Predef.rawValue(), RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x"); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java index f0a6a895958d889f1a046f5a434d4b2354de71d0..7b259a032417427dcf6ccadc1215beee3ae44117 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java @@ -35,6 +35,7 @@ import java.util.Set; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.DCF; import com.oracle.truffle.r.runtime.RError; @@ -49,13 +50,13 @@ import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "readDCF", kind = INTERNAL, parameterNames = {"conn", "fields", "keepwhite"}, behavior = IO) -public abstract class ReadDCF extends RBuiltinNode { +public abstract class ReadDCF extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(ReadDCF.class); casts.arg("conn").defaultError(Message.INVALID_CONNECTION).asIntegerVector().findFirst(); - casts.arg("fields").mapNull(emptyStringVector()).asStringVector(); - casts.arg("keepwhite").mapNull(emptyStringVector()).asStringVector(); + casts.arg("fields").mustNotBeMissing().mapIf(nullValue(), emptyStringVector()).asStringVector(); + casts.arg("keepwhite").mustNotBeMissing().mapIf(nullValue(), emptyStringVector()).asStringVector(); } @Specialization @@ -72,10 +73,10 @@ public abstract class ReadDCF extends RBuiltinNode { } dcf = DCF.read(openConn.readLines(0, true, false), keepWhiteSet); } catch (IOException ex) { - throw RError.error(this, RError.Message.ERROR_READING_CONNECTION, ex.getMessage()); + throw error(RError.Message.ERROR_READING_CONNECTION, ex.getMessage()); } if (dcf == null) { - throw RError.error(this, RError.Message.INVALID_CONNECTION); + throw error(RError.Message.INVALID_CONNECTION); } List<DCF.Fields> records = dcf.getRecords(); int nRecords = records.size(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java index 999f8ef7f3d99c854995c2714c0abe3a884d1d41..c39fa3a1b6f7ff4669953c543aaf40396f4ef25a 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java @@ -39,11 +39,11 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.context.RContext; @RBuiltin(name = "readRenviron", visibility = OFF, kind = INTERNAL, parameterNames = "x", behavior = COMPLEX) -public abstract class ReadREnviron extends RBuiltinNode { +public abstract class ReadREnviron extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(ReadREnviron.class); - casts.arg("x").mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.ARGUMENT_MUST_BE_STRING, "x").asStringVector().findFirst(); + casts.arg("x").mustBe(stringValue(), RError.Message.ARGUMENT_MUST_BE_STRING, "x").asStringVector().findFirst(); } @TruffleBoundary @@ -53,10 +53,10 @@ public abstract class ReadREnviron extends RBuiltinNode { try { RContext.getInstance().stateREnvVars.readEnvironFile(path); } catch (FileNotFoundException ex) { - RError.warning(this, RError.Message.GENERIC, ex.getMessage()); + warning(RError.Message.GENERIC, ex.getMessage()); result = RRuntime.LOGICAL_FALSE; } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); + throw error(RError.Message.GENERIC, ex.getMessage()); } return result; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java index bc5411859c8e3aff340dd5a79000ae01c4e690ff..f5d72cb3b60930338de975a7ebcd8e7a0a3e3862 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java @@ -34,7 +34,7 @@ import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "readline", kind = INTERNAL, parameterNames = "prompt", behavior = IO) -public abstract class Readline extends RBuiltinNode { +public abstract class Readline extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(Readline.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java index 4c53575646846ef0baac6dcc1e11b3bb3532cc2a..5d82e00576a4c32e52906c736c729abb2a467f56 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java @@ -29,7 +29,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.GetCallerFrameNode; @@ -45,9 +44,7 @@ import com.oracle.truffle.r.runtime.data.RFunction; * The {@code Recall} {@code .Internal}. */ @RBuiltin(name = "Recall", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"..."}, nonEvalArgs = {0}, behavior = COMPLEX) -public abstract class Recall extends RBuiltinNode { - - private final BranchProfile errorProfile = BranchProfile.create(); +public abstract class Recall extends RBuiltinNode.Arg1 { @Child private LocalReadVariableNode readArgs = LocalReadVariableNode.create(ArgumentsSignature.VARARG_NAME, false); @@ -64,8 +61,7 @@ public abstract class Recall extends RBuiltinNode { Frame cframe = callerFrame.execute(frame); RFunction function = RArguments.getFunction(cframe); if (function == null) { - errorProfile.enter(); - throw RError.error(RError.SHOW_CALLER, RError.Message.RECALL_CALLED_OUTSIDE_CLOSURE); + throw error(RError.Message.RECALL_CALLED_OUTSIDE_CLOSURE); } /* * The args passed to the Recall internal are ignored, they are always "...". Instead, this diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RecordGraphics.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RecordGraphics.java index 5182327ab41aeac25c16cefd9204729f11e4dc36..90b72ab45c609ecbe571b1c436e4762bc55f5451 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RecordGraphics.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RecordGraphics.java @@ -50,7 +50,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment; * the recording like GnuR does. */ @RBuiltin(name = "recordGraphics", kind = INTERNAL, parameterNames = {"expr", "list", "env"}, behavior = COMPLEX) -public abstract class RecordGraphics extends RBuiltinNode { +public abstract class RecordGraphics extends RBuiltinNode.Arg3 { @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); @Child private RList2EnvNode list2EnvNode = new RList2EnvNode(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RegFinalizer.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RegFinalizer.java index 4703cc2b232534e3199c5fd0d657f590ed8220e0..bade5694f1ec24673a3a70fd5184dd1b2d2d6298 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RegFinalizer.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RegFinalizer.java @@ -37,13 +37,13 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.env.REnvironment; @RBuiltin(name = "reg.finalizer", kind = INTERNAL, parameterNames = {"e", "f", "onexit"}, behavior = COMPLEX) -public abstract class RegFinalizer extends RBuiltinNode { +public abstract class RegFinalizer extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(RegFinalizer.class); casts.arg("e").mustBe(instanceOf(REnvironment.class).or(instanceOf(RExternalPtr.class)), RError.Message.REG_FINALIZER_FIRST); casts.arg("f").mustBe(instanceOf(RFunction.class), RError.Message.REG_FINALIZER_SECOND); - casts.arg("onexit").asLogicalVector().findFirst().notNA(RError.Message.REG_FINALIZER_THIRD).map(toBoolean()); + casts.arg("onexit").asLogicalVector().findFirst().mustNotBeNA(RError.Message.REG_FINALIZER_THIRD).map(toBoolean()); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java index 5d1bd20567546186b848131e658d4c926d1c73c7..83f22bc1cda9ac45a2c3e828750a9722a7d436f2 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java @@ -33,24 +33,38 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import java.util.Arrays; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.api.dsl.TypeSystemReference; +import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.r.nodes.attributes.InitAttributesNode; -import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode; +import com.oracle.truffle.api.profiles.PrimitiveValueProfile; +import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.base.RepeatNodeGen.FastRInternalRepeatNodeGen; +import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineBuilder; +import com.oracle.truffle.r.nodes.function.FormalArguments; +import com.oracle.truffle.r.nodes.function.call.PrepareMatchInternalArguments; +import com.oracle.truffle.r.nodes.function.call.PrepareMatchInternalArgumentsNodeGen; +import com.oracle.truffle.r.nodes.unary.CastNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RAttributesLayout; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.RTypes; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; /** * The {@code rep} builtin works as follows. @@ -72,179 +86,192 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; * </ul> * </ol> */ -@RBuiltin(name = "rep", kind = PRIMITIVE, parameterNames = {"x", "times", "length.out", "each"}, dispatch = INTERNAL_GENERIC, behavior = PURE) -public abstract class Repeat extends RBuiltinNode { +@RBuiltin(name = "rep", kind = PRIMITIVE, parameterNames = {"x", "..."}, dispatch = INTERNAL_GENERIC, behavior = PURE) +public abstract class Repeat extends RBuiltinNode.Arg2 { - protected abstract Object execute(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each); - - private final ConditionProfile lengthOutOrTimes = ConditionProfile.createBinaryProfile(); - private final BranchProfile errorBranch = BranchProfile.create(); - private final ConditionProfile oneTimeGiven = ConditionProfile.createBinaryProfile(); - private final ConditionProfile replicateOnce = ConditionProfile.createBinaryProfile(); - @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create(); - - @Override - public Object[] getDefaultParameterValues() { - return new Object[]{RMissing.instance, 1, RRuntime.INT_NA, 1}; - } + private static final PipelineBuilder PB_TIMES; + private static final PipelineBuilder PB_LENGTH_OUT; + private static final PipelineBuilder PB_EACH; + private static final FormalArguments FORMALS; + private static final int ARG_IDX_TIMES; + private static final int ARG_IDX_LENGHT_OUT; + private static final int ARG_IDX_EACH; static { Casts casts = new Casts(Repeat.class); casts.arg("x").mustBe(abstractVectorValue(), RError.Message.ATTEMPT_TO_REPLICATE, typeName()); - casts.arg("times").defaultError(RError.Message.INVALID_ARGUMENT, "times").mustNotBeNull().asIntegerVector(); - casts.arg("length.out").mustNotBeNull().asIntegerVector().shouldBe(size(1).or(size(0)), RError.Message.FIRST_ELEMENT_USED, "length.out").findFirst(RRuntime.INT_NA, - RError.Message.FIRST_ELEMENT_USED, "length.out").mustBe(intNA().or(gte(0))); - casts.arg("each").asIntegerVector().shouldBe(size(1).or(size(0)), RError.Message.FIRST_ELEMENT_USED, "each").findFirst(1, RError.Message.FIRST_ELEMENT_USED, "each").notNA( - 1).mustBe(gte(0)); - } - protected boolean hasNames(RAbstractVector x) { - return getNames.getNames(x) != null; - } + // prepare cast pipeline nodes for vararg matching + PB_TIMES = new PipelineBuilder("times"); + PB_TIMES.fluent().defaultError(RError.Message.INVALID_ARGUMENT, "times").mustNotBeNull().asIntegerVector(); - private RError invalidTimes() { - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "times"); - } + PB_LENGTH_OUT = new PipelineBuilder("length.out"); + PB_LENGTH_OUT.fluent().asIntegerVector().shouldBe(size(1).or(size(0)), + RError.Message.FIRST_ELEMENT_USED, "length.out").findFirst(RRuntime.INT_NA, + RError.Message.FIRST_ELEMENT_USED, "length.out").mustBe(intNA().or(gte(0))); - @Specialization(guards = {"x.getLength() == 1", "times.getLength() == 1", "each <= 1", "!hasNames(x)"}) - protected RAbstractVector repNoEachNoNamesSimple(RAbstractDoubleVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each) { - int t = times.getDataAt(0); - if (t < 0) { - errorBranch.enter(); - throw invalidTimes(); - } - int length = lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut)) ? lengthOut : t; - double[] data = new double[length]; - Arrays.fill(data, x.getDataAt(0)); - return RDataFactory.createDoubleVector(data, !RRuntime.isNA(x.getDataAt(0))); - } + PB_EACH = new PipelineBuilder("each"); + PB_EACH.fluent().asIntegerVector().shouldBe(size(1).or(size(0)), + RError.Message.FIRST_ELEMENT_USED, "each").findFirst(1, RError.Message.FIRST_ELEMENT_USED, + "each").replaceNA(1).mustBe(gte(0)); - @Specialization(guards = {"each > 1", "!hasNames(x)"}) - protected RAbstractVector repEachNoNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each) { - if (times.getLength() > 1) { - errorBranch.enter(); - throw invalidTimes(); - } - RAbstractVector input = handleEach(x, each); - if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) { - return handleLengthOut(input, lengthOut, false); - } else { - return handleTimes(input, times, false); - } + ArgumentsSignature signature = ArgumentsSignature.get("times", "length.out", "each"); + ARG_IDX_TIMES = 0; + ARG_IDX_LENGHT_OUT = 1; + ARG_IDX_EACH = 2; + FORMALS = FormalArguments.createForBuiltin(new Object[]{1, RRuntime.INT_NA, 1}, signature); } - @Specialization(guards = {"each <= 1", "!hasNames(x)"}) - protected RAbstractVector repNoEachNoNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each) { - if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) { - return handleLengthOut(x, lengthOut, true); - } else { - return handleTimes(x, times, true); - } - } + @Child private FastRInternalRepeat internalNode = FastRInternalRepeatNodeGen.create(); + @Child private CastNode castTimes = PB_TIMES.buildNode(); + @Child private CastNode castLengthOut = PB_LENGTH_OUT.buildNode(); + @Child private CastNode castEach = PB_EACH.buildNode(); + @Child private PrepareMatchInternalArguments prepareArgs = PrepareMatchInternalArgumentsNodeGen.create(FORMALS, this); - @Specialization(guards = {"each > 1", "hasNames(x)"}) - protected RAbstractVector repEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each, - @Cached("create()") InitAttributesNode initAttributes, - @Cached("createNames()") SetFixedAttributeNode putNames) { - if (times.getLength() > 1) { - errorBranch.enter(); - throw invalidTimes(); - } - RAbstractVector input = handleEach(x, each); - RStringVector names = (RStringVector) handleEach(getNames.getNames(x), each); - RVector<?> r; - if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) { - names = (RStringVector) handleLengthOut(names, lengthOut, false); - r = handleLengthOut(input, lengthOut, false); - } else { - names = (RStringVector) handleTimes(names, times, false); - r = handleTimes(input, times, false); - } - putNames.execute(initAttributes.execute(r), names); - return r; + @Override + public Object[] getDefaultParameterValues() { + return new Object[]{RMissing.instance, RArgsValuesAndNames.EMPTY}; } - @Specialization(guards = {"each <= 1", "hasNames(x)"}) - protected RAbstractVector repNoEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each, - @Cached("create()") InitAttributesNode initAttributes, - @Cached("createNames()") SetFixedAttributeNode putNames) { - RStringVector names; - RVector<?> r; - if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) { - names = (RStringVector) handleLengthOut(getNames.getNames(x), lengthOut, true); - r = handleLengthOut(x, lengthOut, true); - } else { - names = (RStringVector) handleTimes(getNames.getNames(x), times, true); - r = handleTimes(x, times, true); - } - putNames.execute(initAttributes.execute(r), names); - return r; - } + @Specialization + protected Object repeat(VirtualFrame frame, RAbstractVector x, RArgsValuesAndNames args) { + RArgsValuesAndNames margs = prepareArgs.execute(args, null); - /** - * Prepare the input vector by replicating its elements. - */ - private static RVector<?> handleEach(RAbstractVector x, int each) { - RVector<?> r = x.createEmptySameType(x.getLength() * each, x.isComplete()); - for (int i = 0; i < x.getLength(); i++) { - for (int j = i * each; j < (i + 1) * each; j++) { - r.transferElementSameType(j, x, i); - } - } - return r; + // cast arguments + Object times = castTimes.doCast(margs.getArgument(ARG_IDX_TIMES)); + Object lengthOut = castLengthOut.doCast(margs.getArgument(ARG_IDX_LENGHT_OUT)); + Object each = castEach.doCast(margs.getArgument(ARG_IDX_EACH)); + + return internalNode.execute(frame, x, times, lengthOut, each); } - /** - * Extend or truncate the vector to a specified length. - */ - private static RVector<?> handleLengthOut(RAbstractVector x, int lengthOut, boolean copyIfSameSize) { - if (x.getLength() == lengthOut) { - return (RVector<?>) (copyIfSameSize ? x.copy() : x); + @TypeSystemReference(RTypes.class) + abstract static class FastRInternalRepeat extends RBaseNode { + + private final ConditionProfile lengthOutOrTimes = ConditionProfile.createBinaryProfile(); + private final ConditionProfile oneTimeGiven = ConditionProfile.createBinaryProfile(); + + @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create(); + + @CompilationFinal private boolean trySimple = true; + + public abstract RAbstractVector execute(VirtualFrame frame, Object... args); + + @Specialization + protected RAbstractVector rep(RAbstractVector xIn, RAbstractIntVector timesIn, int lengthOutIn, int eachIn, + @Cached("createClassProfile()") ValueProfile xProfile, + @Cached("createClassProfile()") ValueProfile timesProfile, + @Cached("createEqualityProfile()") PrimitiveValueProfile lengthOutProfile, + @Cached("createEqualityProfile()") PrimitiveValueProfile eachProfile, + @Cached("createBinaryProfile()") ConditionProfile hasNamesProfile) { + RAbstractVector x = xProfile.profile(xIn); + RAbstractIntVector times = timesProfile.profile(timesIn); + int lengthOut = lengthOutProfile.profile(lengthOutIn); + int each = eachProfile.profile(eachIn); + + // fast path for very simple case of filling with a single double values: + if (trySimple) { + if (x instanceof RAbstractDoubleVector && x.getLength() == 1 && times.getLength() == 1 && each == 1 && getNames.getNames(x) == null) { + RAbstractDoubleVector doubleVector = (RAbstractDoubleVector) x; + int t = times.getDataAt(0); + if (t < 0) { + throw error(RError.Message.INVALID_ARGUMENT, "times"); + } + int length = lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut)) ? lengthOut : t; + double[] data = new double[length]; + Arrays.fill(data, doubleVector.getDataAt(0)); + return RDataFactory.createDoubleVector(data, !RRuntime.isNA(doubleVector.getDataAt(0))); + } else { + CompilerDirectives.transferToInterpreterAndInvalidate(); + trySimple = false; + } + } + return repInternal(x, times, lengthOut, each, hasNamesProfile); } - return x.copyResized(lengthOut, false); - } - /** - * Replicate the vector a given number of times. - */ - private RVector<?> handleTimes(RAbstractVector x, RAbstractIntVector times, boolean copyIfSameSize) { - if (oneTimeGiven.profile(times.getLength() == 1)) { - // only one times value is given - final int howManyTimes = times.getDataAt(0); - if (howManyTimes < 0) { - errorBranch.enter(); - throw invalidTimes(); + private RAbstractVector repInternal(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each, ConditionProfile hasNamesProfile) { + RAbstractVector input = x; + if (each != 1) { + if (each <= 0) { + throw error(RError.Message.INVALID_ARGUMENT, "times"); + } + if (times.getLength() > 1) { + throw error(RError.Message.INVALID_ARGUMENT, "times"); + } + input = handleEach(input, each); } - if (replicateOnce.profile(howManyTimes == 1)) { - return (RVector<?>) (copyIfSameSize ? x.copy() : x); + RVector<?> r; + if (lengthOutOrTimes.profile(RRuntime.isNA(lengthOut))) { + r = handleTimes(input, times); } else { - return x.copyResized(x.getLength() * howManyTimes, false); + r = handleLengthOut(input, lengthOut); } - } else { - // times is a vector with several elements - if (x.getLength() != times.getLength()) { - errorBranch.enter(); - invalidTimes(); - } - // iterate once over the times vector to determine result vector size - int resultLength = 0; - for (int i = 0; i < times.getLength(); i++) { - int t = times.getDataAt(i); - if (t < 0) { - errorBranch.enter(); - throw invalidTimes(); + if (hasNamesProfile != null) { + RStringVector names = getNames.getNames(x); + if (hasNamesProfile.profile(names != null)) { + // handle names - passing null as hasNamesProfile stops the recursion + names = (RStringVector) repInternal(names, times, lengthOut, each, null); + r.initAttributes(RAttributesLayout.createNames(names)); } - resultLength += t; } - // create and populate result vector - RVector<?> r = x.createEmptySameType(resultLength, x.isComplete()); - int wp = 0; // write pointer + return r; + } + + /** + * Prepare the input vector by replicating its elements. + */ + private static RVector<?> handleEach(RAbstractVector x, int each) { + RVector<?> r = x.createEmptySameType(x.getLength() * each, x.isComplete()); for (int i = 0; i < x.getLength(); i++) { - for (int j = 0; j < times.getDataAt(i); ++j, ++wp) { - r.transferElementSameType(wp, x, i); + for (int j = i * each; j < (i + 1) * each; j++) { + r.transferElementSameType(j, x, i); } } return r; } + + /** + * Extend or truncate the vector to a specified length. + */ + private static RVector<?> handleLengthOut(RAbstractVector x, int lengthOut) { + return x.copyResized(lengthOut, false); + } + + /** + * Replicate the vector a given number of times. + */ + private RVector<?> handleTimes(RAbstractVector x, RAbstractIntVector times) { + if (oneTimeGiven.profile(times.getLength() == 1)) { + // only one times value is given + int howManyTimes = times.getDataAt(0); + if (howManyTimes < 0) { + throw error(RError.Message.INVALID_ARGUMENT, "times"); + } + return x.copyResized(x.getLength() * howManyTimes, false); + } else { + // times is a vector with several elements + if (x.getLength() != times.getLength()) { + throw error(RError.Message.INVALID_ARGUMENT, "times"); + } + // iterate once over the times vector to determine result vector size + int resultLength = 0; + for (int i = 0; i < times.getLength(); i++) { + int t = times.getDataAt(i); + if (t < 0) { + throw error(RError.Message.INVALID_ARGUMENT, "times"); + } + resultLength += t; + } + // create and populate result vector + RVector<?> r = x.createEmptySameType(resultLength, x.isComplete()); + int wp = 0; // write pointer + for (int i = 0; i < x.getLength(); i++) { + for (int j = 0; j < times.getDataAt(i); ++j, ++wp) { + r.transferElementSameType(wp, x, i); + } + } + return r; + } + } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java index f376567eced2d4c06962cddf51c185e8bfc5813b..3c27d15d99346612ad8612903740cdf656bb352a 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java @@ -31,11 +31,12 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import java.util.function.IntFunction; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RComplex; +import com.oracle.truffle.r.runtime.data.RComplexVector; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RIntVector; @@ -43,6 +44,7 @@ import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RLogicalVector; import com.oracle.truffle.r.runtime.data.RRawVector; import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; 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.RAbstractLogicalVector; @@ -51,16 +53,15 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "rep.int", kind = INTERNAL, parameterNames = {"x", "times"}, behavior = PURE) -public abstract class RepeatInternal extends RBuiltinNode { +public abstract class RepeatInternal extends RBuiltinNode.Arg2 { private final ConditionProfile timesOneProfile = ConditionProfile.createBinaryProfile(); - private final BranchProfile errorProfile = BranchProfile.create(); static { Casts casts = new Casts(RepeatInternal.class); - casts.arg("x").mustBe(abstractVectorValue(), RError.SHOW_CALLER2, RError.Message.ATTEMPT_TO_REPLICATE, typeName()); - casts.arg("times").defaultError(RError.SHOW_CALLER, RError.Message.INCORRECT_ARG_TYPE, "second").mustBe(abstractVectorValue()).asIntegerVector().mustBe(notEmpty(), - RError.SHOW_CALLER, RError.Message.INVALID_VALUE, "times"); + casts.arg("x").mustBe(abstractVectorValue(), RError.Message.ATTEMPT_TO_REPLICATE, typeName()); + casts.arg("times").defaultError(RError.Message.INCORRECT_ARG_TYPE, "second").mustBe(abstractVectorValue()).asIntegerVector().mustBe(notEmpty(), + RError.Message.INVALID_VALUE, "times"); } @FunctionalInterface @@ -81,8 +82,7 @@ public abstract class RepeatInternal extends RBuiltinNode { if (timesOneProfile.profile(timesLength == 1)) { int timesValue = times.getDataAt(0); if (timesValue < 0) { - errorProfile.enter(); - RError.error(this, RError.Message.INVALID_VALUE, "times"); + throw error(RError.Message.INVALID_VALUE, "times"); } int count = timesValue * valueLength; result = arrayConstructor.apply(count); @@ -97,8 +97,7 @@ public abstract class RepeatInternal extends RBuiltinNode { for (int i = 0; i < timesLength; i++) { int data = times.getDataAt(i); if (data < 0) { - errorProfile.enter(); - RError.error(this, RError.Message.INVALID_VALUE, "times"); + throw error(RError.Message.INVALID_VALUE, "times"); } count += data; } @@ -111,8 +110,7 @@ public abstract class RepeatInternal extends RBuiltinNode { } } } else { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_VALUE, "times"); + throw error(RError.Message.INVALID_VALUE, "times"); } return createResult.create(result, value.isComplete()); } @@ -142,6 +140,50 @@ public abstract class RepeatInternal extends RBuiltinNode { return repInt(value, times, byte[]::new, (array, pos, val, index) -> array[pos] = val.getDataAt(index).getValue(), (array, complete) -> RDataFactory.createRawVector(array)); } + @Specialization + protected RComplexVector repComplex(RAbstractComplexVector value, RAbstractIntVector times) { + int timesLength = times.getLength(); + int valueLength = value.getLength(); + double[] resultArray; + if (timesOneProfile.profile(timesLength == 1)) { + int timesValue = times.getDataAt(0); + if (timesValue < 0) { + throw error(RError.Message.INVALID_VALUE, "times"); + } + resultArray = new double[(timesValue * valueLength) << 1]; + int pos = 0; + for (int i = 0; i < timesValue; i++) { + for (int j = 0; j < valueLength; j++) { + RComplex complex = value.getDataAt(j); + resultArray[pos++] = complex.getRealPart(); + resultArray[pos++] = complex.getImaginaryPart(); + } + } + } else if (timesLength == valueLength) { + int count = 0; + for (int i = 0; i < timesLength; i++) { + int data = times.getDataAt(i); + if (data < 0) { + throw error(RError.Message.INVALID_VALUE, "times"); + } + count += data; + } + resultArray = new double[count << 1]; + int pos = 0; + for (int i = 0; i < valueLength; i++) { + int num = times.getDataAt(i); + RComplex complex = value.getDataAt(i); + for (int j = 0; j < num; j++) { + resultArray[pos++] = complex.getRealPart(); + resultArray[pos++] = complex.getImaginaryPart(); + } + } + } else { + throw error(RError.Message.INVALID_VALUE, "times"); + } + return RDataFactory.createComplexVector(resultArray, value.isComplete()); + } + @Specialization protected RList repList(RList value, int times) { int oldLength = value.getLength(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java index 163552a82d386614439cc55202e6a534b3c5dabb..91f3883d1e6ee06c3d2c4ae1e02c761aa660b6c2 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java @@ -39,18 +39,21 @@ import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @RBuiltin(name = "rep_len", kind = INTERNAL, parameterNames = {"x", "length.out"}, behavior = PURE) -public abstract class RepeatLength extends RBuiltinNode { +public abstract class RepeatLength extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(RepeatLength.class); - casts.arg("x").mustBe(abstractVectorValue(), RError.SHOW_CALLER, RError.Message.ATTEMPT_TO_REPLICATE_NO_VECTOR); + casts.arg("x").allowNull().mustBe(abstractVectorValue(), RError.Message.ATTEMPT_TO_REPLICATE_NO_VECTOR); // with default error message, SHOW_CALLER does not work - casts.arg("length.out").defaultError(RError.SHOW_CALLER, RError.Message.INVALID_VALUE, "length.out").mustNotBeNull().asIntegerVector().mustBe(size(1)).findFirst().mustBe(notIntNA()); + casts.arg("length.out").defaultError(RError.Message.INVALID_VALUE, "length.out").mustNotBeNull().asIntegerVector().mustBe(size(1)).findFirst().mustBe(notIntNA()); } @Specialization @SuppressWarnings("unused") protected RNull repLen(RNull value, int length) { + if (length != 0) { + RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_REPLICATE_NULL); + } return RNull.instance; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Return.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Return.java index e990562976c17c4c4e23cf86f72bdc64776dde0d..643ac7f8f9659f1420067d7a994ecc200b1730fa 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Return.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Return.java @@ -66,7 +66,7 @@ final class ReturnSpecial extends RNode { * {@link FunctionDefinitionNode}. */ @RBuiltin(name = "return", kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX, nonEvalArgs = {0}) -public abstract class Return extends RBuiltinNode { +public abstract class Return extends RBuiltinNode.Arg1 { public static RNode createSpecial(@SuppressWarnings("unused") ArgumentsSignature signature, RNode[] arguments, @SuppressWarnings("unused") boolean inReplacement) { return arguments.length == 1 ? new ReturnSpecial(arguments[0]) : null; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rhome.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rhome.java index 2a735cdb0a6479d47ba055c05c72fa919b364a7e..e538405b680c0171efc9ed33d475eb374a9383b1 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rhome.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rhome.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 @@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; * R.home builtin. */ @RBuiltin(name = "R.home", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) -public abstract class Rhome extends RBuiltinNode { +public abstract class Rhome extends RBuiltinNode.Arg0 { @Specialization @TruffleBoundary diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java index 544075d500a238cd222f6e3253fde3f2e613aa73..ea10c5aea50987a528ff6974e51dbc6aa87ab0f5 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java @@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; -import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ARGUMENT; import static com.oracle.truffle.r.runtime.RError.Message.INVALID_FIRST_ARGUMENT; import static com.oracle.truffle.r.runtime.RError.Message.USE_NULL_ENV_DEFUNCT; @@ -37,13 +36,11 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameSlot; -import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; -import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; @@ -54,30 +51,20 @@ import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; * Note: remove is invoked from builtin wrappers 'rm' and 'remove' that are identical. */ @RBuiltin(name = "remove", visibility = OFF, kind = INTERNAL, parameterNames = {"list", "envir", "inherits"}, behavior = COMPLEX) -public abstract class Rm extends RBuiltinNode { +public abstract class Rm extends RBuiltinNode.Arg3 { private final BranchProfile invalidateProfile = BranchProfile.create(); static { Casts casts = new Casts(Rm.class); - casts.arg("list").mustBe(stringValue(), SHOW_CALLER, INVALID_FIRST_ARGUMENT); - casts.arg("envir").mustNotBeNull(SHOW_CALLER, USE_NULL_ENV_DEFUNCT).mustBe(REnvironment.class, SHOW_CALLER, INVALID_ARGUMENT, "envir"); - casts.arg("inherits").mustBe(numericValue(), SHOW_CALLER, INVALID_ARGUMENT, "inherits").asLogicalVector().findFirst().map(toBoolean()); - } - - // this specialization is for internal use only - // TODO: what internal use? Does it still apply? - @Specialization - @SuppressWarnings("unused") - protected Object rm(VirtualFrame frame, String name, RMissing envir, boolean inherits) { - removeFromFrame(frame, name); - return RNull.instance; + casts.arg("list").mustBe(stringValue(), INVALID_FIRST_ARGUMENT); + casts.arg("envir").mustNotBeNull(USE_NULL_ENV_DEFUNCT).mustBe(REnvironment.class, INVALID_ARGUMENT, "envir"); + casts.arg("inherits").mustBe(numericValue(), INVALID_ARGUMENT, "inherits").asLogicalVector().findFirst().map(toBoolean()); } @Specialization @TruffleBoundary - @SuppressWarnings("unused") - protected Object rm(RAbstractStringVector list, REnvironment envir, boolean inherits) { + protected Object rm(RAbstractStringVector list, REnvironment envir, @SuppressWarnings("unused") boolean inherits) { try { for (int i = 0; i < list.getLength(); i++) { if (envir == REnvironment.globalEnv()) { @@ -87,7 +74,7 @@ public abstract class Rm extends RBuiltinNode { } } } catch (PutException ex) { - throw RError.error(SHOW_CALLER, ex); + throw error(ex); } return RNull.instance; } @@ -103,7 +90,7 @@ public abstract class Rm extends RBuiltinNode { } } if (fs == null) { - RError.warning(SHOW_CALLER, RError.Message.UNKNOWN_OBJECT, x); + warning(RError.Message.UNKNOWN_OBJECT, x); } else { // use null (not an R value) to represent "undefined" FrameSlotChangeMonitor.setObjectAndInvalidate(frame, fs, null, false, invalidateProfile); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java index 13230809bec5a91311616381d6ef0776ef5aebfa..0b5877e50cca45d3da955ba762198481a9f58718 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java @@ -49,7 +49,7 @@ import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "round", kind = PRIMITIVE, parameterNames = {"x", "digits"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) -public abstract class Round extends RBuiltinNode { +public abstract class Round extends RBuiltinNode.Arg2 { public static final UnaryArithmeticFactory ROUND = RoundArithmetic::new; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Row.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Row.java index 245edd7529a5d4e4ac7ee9eeb94e509599404dce..e3c1c874699f60eb4b307736332953ab9fe3acbb 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Row.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Row.java @@ -14,7 +14,6 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size; -import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -27,11 +26,11 @@ import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @RBuiltin(name = "row", kind = INTERNAL, parameterNames = {"dims"}, behavior = PURE) -public abstract class Row extends RBuiltinNode { +public abstract class Row extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(Row.class); - casts.arg("dims").defaultError(SHOW_CALLER, RError.Message.MATRIX_LIKE_REQUIRED, "row").mustBe(integerValue()).asIntegerVector().mustBe(size(2)); + casts.arg("dims").defaultError(RError.Message.MATRIX_LIKE_REQUIRED, "row").mustBe(integerValue()).asIntegerVector().mustBe(size(2)); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java index f476fd860de97627ffa34e21ee1fdb090a7bee96..2a1ebf4a7bb389f9d2ee2a4815503fbc8a4e44fe 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java @@ -12,8 +12,12 @@ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.and; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.not; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; @@ -29,6 +33,7 @@ import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; @@ -45,7 +50,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; public class RowsumFunctions { @RBuiltin(name = "rowsum_matrix", kind = INTERNAL, parameterNames = {"x", "g", "uniqueg", "snarm", "rn"}, behavior = PURE) - public abstract static class Rowsum extends RBuiltinNode { + public abstract static class Rowsum extends RBuiltinNode.Arg5 { private final ConditionProfile typeProfile = ConditionProfile.createBinaryProfile(); private final NACheck na = NACheck.create(); @@ -54,11 +59,11 @@ public class RowsumFunctions { Casts casts = new Casts(Rowsum.class); casts.arg("x").mustBe(integerValue().or(doubleValue()), RError.Message.ROWSUM_NON_NUMERIC); - casts.arg("g").asVector(); + casts.arg("g").mustNotBeMissing().mustBe(and(not(nullValue()), not(instanceOf(RFunction.class)))).asVector(); - casts.arg("uniqueg").asVector(); + casts.arg("uniqueg").mustNotBeMissing().mustBe(and(not(nullValue()), not(instanceOf(RFunction.class)))).asVector(); - casts.arg("snarm").asLogicalVector().findFirst().notNA(RError.Message.INVALID_LOGICAL).map(toBoolean()); + casts.arg("snarm").asLogicalVector().findFirst().mustNotBeNA(RError.Message.INVALID_LOGICAL).map(toBoolean()); casts.arg("rn").mustBe(stringValue(), RError.Message.ROWSUM_NAMES_NOT_CHAR).asStringVector(); } @@ -132,13 +137,12 @@ public class RowsumFunctions { } result = RDataFactory.createDoubleVector(ansd, complete, new int[]{ng, p}); } - Object[] dimNamesData = new Object[2]; - dimNamesData[0] = rn; RList dn2 = xv.materialize().getDimNames(); + Object dn2Obj = RNull.instance; if (dn2 != null && dn2.getLength() >= 2 && dn2.getDataAt(1) != RNull.instance) { - dimNamesData[1] = dn2.getDataAt(1); + dn2Obj = dn2.getDataAt(1); } - RList dimNames = RDataFactory.createList(dimNamesData); + RList dimNames = RDataFactory.createList(new Object[]{rn, dn2Obj}); result.setDimNames(dimNames); return result; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java index 76766dbfcf461522ebdfe0526af8661222a63a6e..cbbb234aaf098b800b6c815bb94cb655b696b8af 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java @@ -52,41 +52,44 @@ import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; -public abstract class S3DispatchFunctions extends RBuiltinNode { +public abstract class S3DispatchFunctions { - @Child private S3FunctionLookupNode methodLookup; - @Child private CallMatcherNode callMatcher; + private static final class Helper extends RBaseNode { + @Child private S3FunctionLookupNode methodLookup; + @Child private CallMatcherNode callMatcher; - private final ConditionProfile callerFrameSlowPath = ConditionProfile.createBinaryProfile(); - private final ConditionProfile topLevelFrameProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile callerFrameSlowPath = ConditionProfile.createBinaryProfile(); + private final ConditionProfile topLevelFrameProfile = ConditionProfile.createBinaryProfile(); - protected S3DispatchFunctions(boolean nextMethod) { - methodLookup = S3FunctionLookupNode.create(true, nextMethod); - callMatcher = CallMatcherNode.create(false); - } + protected Helper(boolean nextMethod) { + methodLookup = S3FunctionLookupNode.create(true, nextMethod); + callMatcher = CallMatcherNode.create(false); + } - protected MaterializedFrame getCallerFrame(VirtualFrame frame) { - MaterializedFrame funFrame = RArguments.getCallerFrame(frame); - if (callerFrameSlowPath.profile(funFrame == null)) { - funFrame = Utils.getCallerFrame(frame, FrameAccess.MATERIALIZE).materialize(); - RError.performanceWarning("slow caller frame access in UseMethod dispatch"); + protected MaterializedFrame getCallerFrame(VirtualFrame frame) { + MaterializedFrame funFrame = RArguments.getCallerFrame(frame); + if (callerFrameSlowPath.profile(funFrame == null)) { + funFrame = Utils.getCallerFrame(frame, FrameAccess.MATERIALIZE).materialize(); + RError.performanceWarning("slow caller frame access in UseMethod dispatch"); + } + // S3 method can be dispatched from top-level where there is no caller frame + return topLevelFrameProfile.profile(funFrame == null) ? frame.materialize() : funFrame; } - // S3 method can be dispatched from top-level where there is no caller frame - return topLevelFrameProfile.profile(funFrame == null) ? frame.materialize() : funFrame; - } - protected Object dispatch(VirtualFrame frame, String generic, RStringVector type, String group, MaterializedFrame callerFrame, MaterializedFrame genericDefFrame, - ArgumentsSignature suppliedSignature, Object[] suppliedArguments) { - Result lookupResult = methodLookup.execute(frame, generic, type, group, callerFrame, genericDefFrame); + protected Object dispatch(VirtualFrame frame, String generic, RStringVector type, String group, MaterializedFrame callerFrame, MaterializedFrame genericDefFrame, + ArgumentsSignature suppliedSignature, Object[] suppliedArguments) { + Result lookupResult = methodLookup.execute(frame, generic, type, group, callerFrame, genericDefFrame); - S3Args s3Args = new S3Args(lookupResult.generic, lookupResult.clazz, lookupResult.targetFunctionName, callerFrame, genericDefFrame, group); - Object result = callMatcher.execute(frame, suppliedSignature, suppliedArguments, lookupResult.function, lookupResult.targetFunctionName, s3Args); - return result; + S3Args s3Args = new S3Args(lookupResult.generic, lookupResult.clazz, lookupResult.targetFunctionName, callerFrame, genericDefFrame, group); + Object result = callMatcher.execute(frame, suppliedSignature, suppliedArguments, lookupResult.function, lookupResult.targetFunctionName, s3Args); + return result; + } } @RBuiltin(name = "UseMethod", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"generic", "object"}, behavior = COMPLEX) - public abstract static class UseMethod extends S3DispatchFunctions { + public abstract static class UseMethod extends RBuiltinNode.Arg2 { /* * TODO: If more than two parameters are passed to UseMethod the extra parameters are @@ -95,8 +98,8 @@ public abstract class S3DispatchFunctions extends RBuiltinNode { @Child private ClassHierarchyNode classHierarchyNode = ClassHierarchyNodeGen.create(true, true); @Child private PromiseCheckHelperNode promiseCheckHelper; + @Child private Helper helper = new Helper(false); - private final BranchProfile errorProfile = BranchProfile.create(); private final BranchProfile firstArgMissing = BranchProfile.create(); private final ConditionProfile argMissingProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile argsValueAndNamesProfile = ConditionProfile.createBinaryProfile(); @@ -105,10 +108,6 @@ public abstract class S3DispatchFunctions extends RBuiltinNode { Casts.noCasts(UseMethod.class); } - protected UseMethod() { - super(false); - } - @Specialization protected Object execute(VirtualFrame frame, String generic, Object arg) { Object dispatchedObject; @@ -120,12 +119,12 @@ public abstract class S3DispatchFunctions extends RBuiltinNode { } RStringVector type = dispatchedObject == null ? RDataFactory.createEmptyStringVector() : classHierarchyNode.execute(dispatchedObject); - MaterializedFrame callerFrame = getCallerFrame(frame); + MaterializedFrame callerFrame = helper.getCallerFrame(frame); MaterializedFrame genericDefFrame = RArguments.getEnclosingFrame(frame); ArgumentsSignature suppliedSignature = RArguments.getSuppliedSignature(frame); Object[] suppliedArguments = RArguments.getArguments(frame); - Object result = dispatch(frame, generic, type, null, callerFrame, genericDefFrame, suppliedSignature, suppliedArguments); + Object result = helper.dispatch(frame, generic, type, null, callerFrame, genericDefFrame, suppliedSignature, suppliedArguments); throw new ReturnException(result, RArguments.getCall(frame)); } @@ -136,8 +135,8 @@ public abstract class S3DispatchFunctions extends RBuiltinNode { */ private Object getEnclosingArg(VirtualFrame frame, String generic) { if (RArguments.getArgumentsLength(frame) == 0 || RArguments.getArgument(frame, 0) == null) { - errorProfile.enter(); - throw RError.error(this, RError.Message.UNKNOWN_FUNCTION_USE_METHOD, generic, RRuntime.toString(RNull.instance)); + CompilerDirectives.transferToInterpreter(); + throw error(RError.Message.UNKNOWN_FUNCTION_USE_METHOD, generic, RRuntime.toString(RNull.instance)); } Object enclosingArg = RArguments.getArgument(frame, 0); if (argsValueAndNamesProfile.profile(enclosingArg instanceof RArgsValuesAndNames)) { @@ -175,7 +174,7 @@ public abstract class S3DispatchFunctions extends RBuiltinNode { } @RBuiltin(name = "NextMethod", visibility = CUSTOM, kind = SUBSTITUTE, parameterNames = {"generic", "object", "..."}, behavior = COMPLEX) - public abstract static class NextMethod extends S3DispatchFunctions { + public abstract static class NextMethod extends RBuiltinNode.Arg3 { @Child private LocalReadVariableNode rvnGroup = LocalReadVariableNode.create(RRuntime.R_DOT_GROUP, false); @Child private LocalReadVariableNode rvnClass = LocalReadVariableNode.create(RRuntime.R_DOT_CLASS, false); @@ -187,8 +186,9 @@ public abstract class S3DispatchFunctions extends RBuiltinNode { @Child private CollectArgumentsNode collectArguments = CollectArgumentsNodeGen.create(); @Child private PromiseHelperNode promiseHelper; + @Child private ClassHierarchyNode hierarchy; + @Child private Helper helper = new Helper(true); - private final BranchProfile errorProfile = BranchProfile.create(); private final ConditionProfile emptyArgsProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile genericCallFrameNullProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile genericDefFrameNullProfile = ConditionProfile.createBinaryProfile(); @@ -196,15 +196,12 @@ public abstract class S3DispatchFunctions extends RBuiltinNode { private final ValueProfile parameterSignatureProfile = ValueProfile.createIdentityProfile(); private final ValueProfile suppliedParameterSignatureProfile = ValueProfile.createIdentityProfile(); + private final ValueProfile rootNodeProfile = ValueProfile.createClassProfile(); static { Casts.noCasts(NextMethod.class); } - protected NextMethod() { - super(true); - } - @Override public Object[] getDefaultParameterValues() { return new Object[]{RNull.instance, RNull.instance, RArgsValuesAndNames.EMPTY}; @@ -218,8 +215,7 @@ public abstract class S3DispatchFunctions extends RBuiltinNode { protected Object nextMethod(VirtualFrame frame, @SuppressWarnings("unused") Object ignoredGeneric, Object obj, RArgsValuesAndNames args) { String generic = (String) rvnGeneric.execute(frame); if (generic == null || generic.isEmpty()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.GEN_FUNCTION_NOT_SPECIFIED); + throw error(RError.Message.GEN_FUNCTION_NOT_SPECIFIED); } return nextMethod(frame, generic, obj, args); } @@ -243,7 +239,7 @@ public abstract class S3DispatchFunctions extends RBuiltinNode { // arguments passed to NextMethod, the later override the former on a name clash ArgumentsSignature finalSignature; ArgumentsSignature suppliedSignature = suppliedParameterSignatureProfile.profile(RArguments.getSuppliedSignature(frame)); - Object[] suppliedArguments = collectArguments.execute(frame, parameterSignatureProfile.profile(RArguments.getSignature(frame))); + Object[] suppliedArguments = collectArguments.execute(frame, parameterSignatureProfile.profile(RArguments.getSignature(frame, rootNodeProfile))); if (emptyArgsProfile.profile(args == RArgsValuesAndNames.EMPTY)) { finalSignature = suppliedSignature; } else { @@ -255,7 +251,7 @@ public abstract class S3DispatchFunctions extends RBuiltinNode { suppliedArguments = combinedResult.getArguments(); finalSignature = combinedResult.getSignature(); } - return dispatch(frame, generic, readType(frame), group, genericCallFrame, genericDefFrame, finalSignature, suppliedArguments); + return helper.dispatch(frame, generic, readType(frame), group, genericCallFrame, genericDefFrame, finalSignature, suppliedArguments); } private MaterializedFrame getDefFrame(VirtualFrame frame) { @@ -290,15 +286,17 @@ public abstract class S3DispatchFunctions extends RBuiltinNode { } if (RArguments.getArgumentsLength(frame) == 0 || RArguments.getArgument(frame, 0) == null || (!(RArguments.getArgument(frame, 0) instanceof RAbstractContainer) && !(RArguments.getArgument(frame, 0) instanceof RPromise))) { - errorProfile.enter(); - throw RError.error(this, RError.Message.OBJECT_NOT_SPECIFIED); + throw error(RError.Message.OBJECT_NOT_SPECIFIED); } Object arg = RArguments.getArgument(frame, 0); if (arg instanceof RPromise) { arg = promiseHelper.evaluate(frame, (RPromise) arg); } - RAbstractContainer enclosingArg = (RAbstractContainer) arg; - return enclosingArg.getClassHierarchy(); + if (hierarchy == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + hierarchy = insert(ClassHierarchyNode.createWithImplicit()); + } + return hierarchy.execute(arg); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java index 961dd4dfee08e12bf3c80324ee90fcd0a5b6aee1..1e79a7792b9ff3253a0e59fce872de77ba2dbc3a 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java @@ -24,10 +24,10 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.isFinite; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lt; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.mustBe; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; -import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ARGUMENT; import static com.oracle.truffle.r.runtime.RError.Message.INVALID_FIRST_ARGUMENT; import static com.oracle.truffle.r.runtime.RError.Message.VECTOR_SIZE_NA_NAN; @@ -44,24 +44,24 @@ import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.rng.RRNG; @RBuiltin(name = "sample", kind = INTERNAL, parameterNames = {"x", "size", "replace", "prob"}, behavior = MODIFIES_STATE) -public abstract class Sample extends RBuiltinNode { +public abstract class Sample extends RBuiltinNode.Arg4 { private final ConditionProfile sampleSizeProfile = ConditionProfile.createBinaryProfile(); static { Casts casts = new Casts(Sample.class); - casts.arg("x").defaultError(SHOW_CALLER, INVALID_FIRST_ARGUMENT).allowNull().mustBe(integerValue().or(doubleValue())).notNA(SHOW_CALLER, VECTOR_SIZE_NA_NAN).mapIf(doubleValue(), - chain(asDoubleVector()).with(findFirst().doubleElement()).with(mustBe(isFinite(), SHOW_CALLER, VECTOR_SIZE_NA_NAN)).with( - mustBe(lt(4.5e15), SHOW_CALLER, VECTOR_SIZE_TOO_LARGE)).end()).asIntegerVector().findFirst().mustBe(gte0()); - casts.arg("size").defaultError(SHOW_CALLER, INVALID_ARGUMENT, "size").mustBe(integerValue().or(doubleValue()).or(stringValue())).asIntegerVector().findFirst().defaultError(SHOW_CALLER, - INVALID_ARGUMENT, "size").notNA().mustBe(gte0()); - casts.arg("replace").mustBe(integerValue().or(doubleValue()).or(logicalValue())).asLogicalVector().mustBe(singleElement()).findFirst().notNA().map(toBoolean()); - casts.arg("prob").asDoubleVector(); + casts.arg("x").defaultError(INVALID_FIRST_ARGUMENT).mustBe(integerValue().or(doubleValue())).mustNotBeNA(VECTOR_SIZE_NA_NAN).mapIf(doubleValue(), + chain(asDoubleVector()).with(findFirst().doubleElement()).with(mustBe(isFinite(), VECTOR_SIZE_NA_NAN)).with( + mustBe(lt(4.5e15), VECTOR_SIZE_TOO_LARGE)).end()).asIntegerVector().findFirst().mustBe(gte0()); + casts.arg("size").defaultError(INVALID_ARGUMENT, "size").mustBe(integerValue().or(doubleValue()).or(stringValue())).asIntegerVector().findFirst().mustNotBeNA(INVALID_ARGUMENT, "size").mustBe( + gte0(), INVALID_ARGUMENT, "size"); + casts.arg("replace").mustBe(integerValue().or(doubleValue()).or(logicalValue())).asLogicalVector().mustBe(singleElement()).findFirst().mustNotBeNA().map(toBoolean()); + casts.arg("prob").mustNotBeMissing().mustBe(doubleValue().or(nullValue())).asDoubleVector(); } // Validation that correlates two or more argument values (note: positiveness of prob is checked @@ -71,39 +71,39 @@ public abstract class Sample extends RBuiltinNode { return !isRepeatable && size > x; } - protected static boolean invalidProb(final int x, final RDoubleVector prob) { + protected static boolean invalidProb(final int x, final RAbstractDoubleVector prob) { return prob.getLength() != x; } @Specialization(guards = "invalidProb(x, prob)") @SuppressWarnings("unused") - protected RIntVector doSampleInvalidProb(final int x, final int size, final boolean isRepeatable, final RDoubleVector prob) { + protected RIntVector doSampleInvalidProb(final int x, final int size, final boolean isRepeatable, final RAbstractDoubleVector prob) { CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.INCORRECT_NUM_PROB); + throw error(RError.Message.INCORRECT_NUM_PROB); } @Specialization(guards = "largerPopulation(x, size, isRepeatable)") @SuppressWarnings("unused") - protected RIntVector doSampleLargerPopulation(final int x, final int size, final boolean isRepeatable, final RDoubleVector prob) { + protected RIntVector doSampleLargerPopulation(final int x, final int size, final boolean isRepeatable, final RAbstractDoubleVector prob) { CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.SAMPLE_LARGER_THAN_POPULATION); + throw error(RError.Message.SAMPLE_LARGER_THAN_POPULATION); } @SuppressWarnings("unused") @Specialization(guards = "largerPopulation(x, size, isRepeatable)") protected RIntVector doSampleInvalidLargerPopulation(final int x, final int size, final boolean isRepeatable, final RNull prob) { CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.INCORRECT_NUM_PROB); + throw error(RError.Message.INCORRECT_NUM_PROB); } // Actual specializations: @Specialization(guards = {"!invalidProb(x, prob)", "!largerPopulation(x, size, isRepeatable)", "isRepeatable"}) @TruffleBoundary - protected RIntVector doSampleWithReplacement(final int x, final int size, final boolean isRepeatable, final RDoubleVector prob) { + protected RIntVector doSampleWithReplacement(final int x, final int size, final boolean isRepeatable, final RAbstractDoubleVector prob) { // The following code is transcribed from GNU R src/main/random.c lines 493-501 in // function do_sample. - double[] probArray = prob.getDataCopy(); + double[] probArray = prob.materialize().getDataCopy(); fixupProbability(probArray, x, size, isRepeatable); int nc = 0; for (double aProb : probArray) { @@ -121,8 +121,8 @@ public abstract class Sample extends RBuiltinNode { @Specialization(guards = {"!invalidProb(x, prob)", "!largerPopulation(x, size, isRepeatable)", "!isRepeatable"}) @TruffleBoundary - protected RIntVector doSampleNoReplacement(final int x, final int size, final boolean isRepeatable, final RDoubleVector prob) { - double[] probArray = prob.getDataCopy(); + protected RIntVector doSampleNoReplacement(final int x, final int size, final boolean isRepeatable, final RAbstractDoubleVector prob) { + double[] probArray = prob.materialize().getDataCopy(); fixupProbability(probArray, x, size, isRepeatable); return RDataFactory.createIntVector(probSampleWithoutReplace(x, probArray, size), RDataFactory.COMPLETE_VECTOR); } @@ -161,10 +161,10 @@ public abstract class Sample extends RBuiltinNode { double probSum = 0; for (double aProb : probArray) { if (!RRuntime.isFinite(aProb)) { - throw RError.error(this, RError.Message.NA_IN_PROB_VECTOR); + throw error(RError.Message.NA_IN_PROB_VECTOR); } if (aProb < 0) { - throw RError.error(this, RError.Message.NEGATIVE_PROBABILITY); + throw error(RError.Message.NEGATIVE_PROBABILITY); } if (aProb > 0) { probSum += aProb; @@ -172,7 +172,7 @@ public abstract class Sample extends RBuiltinNode { } } if (nonZeroProbCount == 0 || (!isRepeatable && size > nonZeroProbCount)) { - throw RError.error(this, RError.Message.TOO_FEW_POSITIVE_PROBABILITY); + throw error(RError.Message.TOO_FEW_POSITIVE_PROBABILITY); } for (int i = 0; i < x; i++) { probArray[i] /= probSum; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java index 8b1ad3e4b693e339e09038e755dcb26eef53065f..8adbb2699ea6c5c07ab9dd6539d04ffc8455e162 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java @@ -17,7 +17,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte0; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.isFinite; -import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; import static com.oracle.truffle.r.runtime.RError.Message.ALGORITHM_FOR_SIZE_N_DIV_2; import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ARGUMENT; import static com.oracle.truffle.r.runtime.RError.Message.INVALID_FIRST_ARGUMENT; @@ -25,13 +24,9 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.MODIFIES_STATE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.dsl.TypeSystemReference; -import com.oracle.truffle.api.profiles.BranchProfile; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.Collections.NonRecursiveHashSetDouble; import com.oracle.truffle.r.runtime.Collections.NonRecursiveHashSetInt; -import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDoubleVector; @@ -42,19 +37,16 @@ import com.oracle.truffle.r.runtime.rng.RRNG; * Sample2 is more efficient special case implementation of {@link Sample}. */ @RBuiltin(name = "sample2", kind = INTERNAL, parameterNames = {"x", "size"}, behavior = MODIFIES_STATE) -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) -public abstract class Sample2 extends RBuiltinNode { +public abstract class Sample2 extends RBuiltinNode.Arg2 { private static final double U = 33554432.0; static final double MAX_INT = Integer.MAX_VALUE; - private final BranchProfile errorProfile = BranchProfile.create(); - static { Casts casts = new Casts(Sample2.class); - casts.arg("x").defaultError(SHOW_CALLER, INVALID_FIRST_ARGUMENT).allowNull().mustBe(integerValue().or(doubleValue())).notNA(SHOW_CALLER, + casts.arg("x").defaultError(INVALID_FIRST_ARGUMENT).mustBe(integerValue().or(doubleValue())).mustNotBeNA( INVALID_FIRST_ARGUMENT).asDoubleVector().findFirst().mustBe(gte(0.0)).mustBe(isFinite()); - casts.arg("size").defaultError(SHOW_CALLER, INVALID_ARGUMENT, "size").mustBe(integerValue().or(doubleValue())).asIntegerVector().findFirst().defaultError(SHOW_CALLER, INVALID_ARGUMENT, - "size").notNA().mustBe(gte0()); + casts.arg("size").defaultError(INVALID_ARGUMENT, "size").mustBe(integerValue().or(doubleValue())).asIntegerVector().findFirst().mustNotBeNA(INVALID_ARGUMENT, + "size").mustBe(gte0(), INVALID_ARGUMENT, "size"); } @Specialization(guards = "x > MAX_INT") @@ -101,8 +93,7 @@ public abstract class Sample2 extends RBuiltinNode { private void validate(double x, int size) { if (size > x / 2) { - errorProfile.enter(); - throw RError.error(SHOW_CALLER, ALGORITHM_FOR_SIZE_N_DIV_2); + throw error(ALGORITHM_FOR_SIZE_N_DIV_2); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java index d80ec47fd7af1df9e9f57671b3595dd49f450b64..db79d22096f48210e9f174659109dc6e1f9782b1 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java @@ -14,10 +14,13 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.charAt0; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyStringVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.length; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lengthLte; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lt; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; @@ -26,11 +29,11 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import java.io.IOException; import java.util.LinkedList; +import java.util.regex.Pattern; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.unary.CastToVectorNode; @@ -44,13 +47,9 @@ import com.oracle.truffle.r.runtime.conn.RConnection; import com.oracle.truffle.r.runtime.conn.StdConnections; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RDouble; -import com.oracle.truffle.r.runtime.data.RInteger; +import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RLogical; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RRaw; -import com.oracle.truffle.r.runtime.data.RString; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @@ -59,13 +58,12 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "scan", kind = INTERNAL, parameterNames = {"file", "what", "nmax", "sep", "dec", "quote", "skip", "nlines", "na.strings", "flush", "fill", "strip.white", "quiet", "blank.lines.skip", "multi.line", "comment.char", "allowEscapes", "encoding", "skipNull"}, behavior = IO) -public abstract class Scan extends RBuiltinNode { +public abstract class Scan extends RBuiltinNode.Arg19 { private static final int SCAN_BLOCKSIZE = 1000; private static final int NO_COMCHAR = 100000; /* won't occur even in Unicode */ private final NACheck naCheck = NACheck.create(); - private final BranchProfile errorProfile = BranchProfile.create(); @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create(); @Child private CastToVectorNode castVector; @@ -75,7 +73,7 @@ public abstract class Scan extends RBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); castVector = insert(CastToVectorNodeGen.create(false)); } - return ((RAbstractVector) castVector.execute(value)).materialize(); + return ((RAbstractVector) castVector.doCast(value)).materialize(); } @SuppressWarnings("unused") @@ -83,6 +81,7 @@ public abstract class Scan extends RBuiltinNode { RAbstractStringVector naStrings = null; boolean quiet = false; String sepchar = null; + String sepregex = null; char decchar = '.'; String quoteset = null; int comchar = NO_COMCHAR; @@ -104,42 +103,42 @@ public abstract class Scan extends RBuiltinNode { Casts casts = new Casts(Scan.class); casts.arg("file").defaultError(Message.INVALID_CONNECTION).mustNotBeNull().asIntegerVector().findFirst(); - casts.arg("what").asVector(); + casts.arg("what").mustNotBeMissing().mustBe(nullValue().not()).mustBe(instanceOf(RFunction.class).not()).asVector(); - casts.arg("nmax").asIntegerVector().findFirst(0).notNA(0).mapIf(lt(0), constant(0)); + casts.arg("nmax").asIntegerVector().findFirst(0).replaceNA(0).mapIf(lt(0), constant(0)); - casts.arg("sep").allowNull().mustBe(stringValue()).asStringVector().findFirst("").mustBe(lengthLte(1), RError.Message.MUST_BE_ONE_BYTE, "'sep' value"); + casts.arg("sep").mapNull(emptyStringVector()).mustBe(stringValue()).asStringVector().findFirst("").mustBe(lengthLte(1), RError.Message.MUST_BE_ONE_BYTE, "'sep' value"); - casts.arg("dec").allowNull().defaultError(RError.Message.INVALID_DECIMAL_SEP).mustBe(stringValue()).asStringVector().findFirst(".").mustBe(length(1), + casts.arg("dec").defaultError(RError.Message.INVALID_DECIMAL_SEP).mapNull(constant(".")).mustBe(stringValue()).asStringVector().findFirst(".").mustBe(length(1), RError.Message.MUST_BE_ONE_BYTE, "'sep' value"); casts.arg("quote").defaultError(RError.Message.INVALID_QUOTE_SYMBOL).mapNull(constant("")).mustBe(stringValue()).asStringVector().findFirst(""); - casts.arg("skip").asIntegerVector().findFirst(0).notNA(0).mapIf(lt(0), constant(0)); + casts.arg("skip").asIntegerVector().findFirst(0).replaceNA(0).mapIf(lt(0), constant(0)); - casts.arg("nlines").asIntegerVector().findFirst(0).notNA(0).mapIf(lt(0), constant(0)); + casts.arg("nlines").asIntegerVector().findFirst(0).replaceNA(0).mapIf(lt(0), constant(0)); casts.arg("na.strings").mustBe(stringValue()); - casts.arg("flush").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean()); + casts.arg("flush").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); - casts.arg("fill").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean()); + casts.arg("fill").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); casts.arg("strip.white").mustBe(logicalValue()); - casts.arg("quiet").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).notNA(RRuntime.LOGICAL_FALSE).map(toBoolean()); + casts.arg("quiet").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).replaceNA(RRuntime.LOGICAL_FALSE).map(toBoolean()); - casts.arg("blank.lines.skip").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).notNA(RRuntime.LOGICAL_TRUE).map(toBoolean()); + casts.arg("blank.lines.skip").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).replaceNA(RRuntime.LOGICAL_TRUE).map(toBoolean()); - casts.arg("multi.line").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).notNA(RRuntime.LOGICAL_TRUE).map(toBoolean()); + casts.arg("multi.line").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).replaceNA(RRuntime.LOGICAL_TRUE).map(toBoolean()); - casts.arg("comment.char").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().mustBe(lengthLte(1)).map(charAt0(RRuntime.INT_NA)).notNA(NO_COMCHAR); + casts.arg("comment.char").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().mustBe(lengthLte(1)).map(charAt0(RRuntime.INT_NA)).replaceNA(NO_COMCHAR); - casts.arg("allowEscapes").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("allowEscapes").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); casts.arg("encoding").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst(); - casts.arg("skipNull").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("skipNull").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } @@ -154,6 +153,7 @@ public abstract class Scan extends RBuiltinNode { // TODO: some sort of character translation happens here? data.sepchar = sep.isEmpty() ? null : sep.substring(0, 1); + data.sepregex = sep.isEmpty() ? null : Pattern.quote(sep.substring(0, 1)); // TODO: some sort of character translation happens here? data.decchar = dec.charAt(0); @@ -164,8 +164,7 @@ public abstract class Scan extends RBuiltinNode { data.naStrings = naStringsVec; if (stripVec.getLength() != 1 && stripVec.getLength() != what.getLength()) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_LENGTH, "strip.white"); + throw error(RError.Message.INVALID_LENGTH, "strip.white"); } byte strip = stripVec.getDataAt(0); @@ -199,7 +198,7 @@ public abstract class Scan extends RBuiltinNode { return scanVector(what, nmax, nlines, flush, strip == RRuntime.LOGICAL_TRUE, blSkip, data); } } catch (IOException x) { - throw RError.error(this, RError.Message.CANNOT_READ_CONNECTION); + throw error(RError.Message.CANNOT_READ_CONNECTION); } } @@ -253,7 +252,7 @@ public abstract class Scan extends RBuiltinNode { // first iteration if (quoteInd == -1) { // no quotes at all - return data.sepchar == null ? s.split("\\s+") : s.split(data.sepchar); + return data.sepregex == null ? s.split("\\s+") : s.split(data.sepregex); } else { sb = new StringBuilder(); } @@ -277,7 +276,7 @@ public abstract class Scan extends RBuiltinNode { assert sepInd >= 0; // everything from the beginning of str becomes part of this time and item // processing is completed (also eat up separators) - String[] tuple = data.sepchar == null ? str.split("\\s+", 2) : str.split(data.sepchar, 2); + String[] tuple = data.sepregex == null ? str.split("\\s+", 2) : str.split(data.sepregex, 2); assert tuple.length == 2; sb.append(tuple[0]); str = tuple[1]; @@ -300,7 +299,7 @@ public abstract class Scan extends RBuiltinNode { continue; } else { if (data.quoteset.length() == 0) { - return data.sepchar == null ? s.split("\\s+") : s.split(data.sepchar); + return data.sepregex == null ? s.split("\\s+") : s.split(data.sepregex); } else { return getQuotedItems(data, s); } @@ -322,15 +321,14 @@ public abstract class Scan extends RBuiltinNode { int nc = what.getLength(); if (nc == 0) { - throw RError.error(this, RError.Message.EMPTY_WHAT); + throw error(RError.Message.EMPTY_WHAT); } int blockSize = maxRecords > 0 ? maxRecords : (maxLines > 0 ? maxLines : SCAN_BLOCKSIZE); - RList list = RDataFactory.createList(new Object[nc]); + RList list = RDataFactory.createList(nc); for (int i = 0; i < nc; i++) { if (what.getDataAt(i) == RNull.instance) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "what"); + throw error(RError.Message.INVALID_ARGUMENT, "what"); } else { RAbstractVector vec = castVector(what.getDataAt(i)); list.updateDataAt(i, vec.createEmptySameType(blockSize, RDataFactory.COMPLETE_VECTOR), null); @@ -367,7 +365,7 @@ public abstract class Scan extends RBuiltinNode { n = 0; break; } else if (!multiLine) { - throw RError.error(this, RError.Message.LINE_ELEMENTS, lines + 1, nc); + throw error(RError.Message.LINE_ELEMENTS, lines + 1, nc); } else { strItems = getItems(data, blSkip); // Checkstyle: stop modified control variable check @@ -417,7 +415,7 @@ public abstract class Scan extends RBuiltinNode { if (n > 0 && n < nc) { if (!fill) { - RError.warning(this, RError.Message.ITEMS_NOT_MULTIPLE); + warning(RError.Message.ITEMS_NOT_MULTIPLE); } fillEmpty(n, nc, records, list, data); records++; @@ -506,53 +504,45 @@ public abstract class Scan extends RBuiltinNode { } private static Object extractItem(RAbstractVector what, String buffer, LocalData data) { - if (what.getElementClass() == RLogical.class) { - if (isNaString(buffer, 0, data)) { - return RRuntime.LOGICAL_NA; - } else { - return RRuntime.string2logicalNoCheck(buffer); - } - } - if (what.getElementClass() == RInteger.class) { - if (isNaString(buffer, 0, data)) { - return RRuntime.INT_NA; - } else { - return RRuntime.string2intNoCheck(buffer); - } - } - - if (what.getElementClass() == RDouble.class) { - if (isNaString(buffer, 0, data)) { - return RRuntime.DOUBLE_NA; - } else { - return RRuntime.string2doubleNoCheck(buffer); - } - } - - if (what.getElementClass() == RComplex.class) { - if (isNaString(buffer, 0, data)) { - return RRuntime.createComplexNA(); - } else { - return RRuntime.string2complexNoCheck(buffer); - } - } - - if (what.getElementClass() == RString.class) { - if (isNaString(buffer, 1, data)) { - return RRuntime.STRING_NA; - } else { - return buffer; - } - } - - if (what.getElementClass() == RRaw.class) { - if (isNaString(buffer, 0, data)) { - return RDataFactory.createRaw((byte) 0); - } else { - return RRuntime.string2raw(buffer); - } + switch (what.getRType()) { + case Logical: + if (isNaString(buffer, 0, data)) { + return RRuntime.LOGICAL_NA; + } else { + return RRuntime.string2logicalNoCheck(buffer); + } + case Integer: + if (isNaString(buffer, 0, data)) { + return RRuntime.INT_NA; + } else { + return RRuntime.string2intNoCheck(buffer); + } + case Double: + if (isNaString(buffer, 0, data)) { + return RRuntime.DOUBLE_NA; + } else { + return RRuntime.string2doubleNoCheck(buffer); + } + case Complex: + if (isNaString(buffer, 0, data)) { + return RComplex.createNA(); + } else { + return RRuntime.string2complexNoCheck(buffer); + } + case Character: + if (isNaString(buffer, 1, data)) { + return RRuntime.STRING_NA; + } else { + return buffer; + } + case Raw: + if (isNaString(buffer, 0, data)) { + return RDataFactory.createRaw((byte) 0); + } else { + return RRuntime.string2raw(buffer); + } + default: + throw RInternalError.shouldNotReachHere(); } - - throw RInternalError.shouldNotReachHere(); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java index 27ec4be7937f911e99d9d12c24f4df2a544bf731..bc951e221bd5010a19ddf800a1ce22ed3663291c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java @@ -12,7 +12,9 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingConstant; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notIntNA; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size; import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder; import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC; @@ -61,7 +63,7 @@ import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RSequence; import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.RTypesFlatLayout; +import com.oracle.truffle.r.runtime.data.RTypes; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -99,7 +101,7 @@ public final class SeqFunctions { } } - @TypeSystemReference(RTypesFlatLayout.class) + @TypeSystemReference(RTypes.class) public abstract static class IsNumericNode extends Node { public abstract boolean execute(Object obj); @@ -129,7 +131,7 @@ public final class SeqFunctions { } } - @TypeSystemReference(RTypesFlatLayout.class) + @TypeSystemReference(RTypes.class) public abstract static class IsMissingOrNumericNode extends IsNumericNode { @Specialization @@ -138,7 +140,7 @@ public final class SeqFunctions { } } - @TypeSystemReference(RTypesFlatLayout.class) + @TypeSystemReference(RTypes.class) public abstract static class GetIntegralNumericNode extends Node { public abstract int execute(Object obj); @@ -182,7 +184,7 @@ public final class SeqFunctions { return IsIntegralNumericNodeGen.create(true); } - @TypeSystemReference(RTypesFlatLayout.class) + @TypeSystemReference(RTypes.class) @ImportStatic(SeqFunctions.class) public abstract static class SeqFastPath extends FastPathAdapter { @Specialization(guards = {"!hasClass(args, getClassAttributeNode)", "lengthSpecials(args)"}) @@ -195,9 +197,9 @@ public final class SeqFunctions { @Cached("createIsMissingOrNumericNode()") IsMissingOrNumericNode fromCheck) { if (isNumericProfile.profile(fromCheck.execute(args.getArgument(0)))) { if (args.getLength() == 1) { - return seqInt.execute(frame, RMissing.instance, RMissing.instance, RMissing.instance, args.getArgument(0), RMissing.instance); + return seqInt.execute(frame, RMissing.instance, RMissing.instance, RMissing.instance, args.getArgument(0), RMissing.instance, RMissing.instance); } else { - return seqInt.execute(frame, args.getArgument(0), RMissing.instance, RMissing.instance, args.getArgument(1), RMissing.instance); + return seqInt.execute(frame, args.getArgument(0), RMissing.instance, RMissing.instance, args.getArgument(1), RMissing.instance, RMissing.instance); } } else { return null; @@ -215,7 +217,7 @@ public final class SeqFunctions { @Cached("createIsMissingOrNumericNode()") @SuppressWarnings("unused") IsMissingOrNumericNode byCheck) { Object[] rargs = reorderedArguments(args, seqIntFunction); if (isNumericProfile.profile(fromCheck.execute(rargs[0]) && toCheck.execute(rargs[1]) && toCheck.execute(rargs[2]))) { - return seqInt.execute(frame, rargs[0], rargs[1], rargs[2], rargs[3], rargs[4]); + return seqInt.execute(frame, rargs[0], rargs[1], rargs[2], rargs[3], rargs[4], RMissing.instance); } else { return null; } @@ -298,7 +300,7 @@ public final class SeqFunctions { * Essentially the same as {@link SeqFastPath} but since the signature is explicit there is no * need to reorder arguments. */ - @TypeSystemReference(RTypesFlatLayout.class) + @TypeSystemReference(RTypes.class) public abstract static class SeqDefaultFastPath extends FastPathAdapter { @SuppressWarnings("unused") @Specialization(guards = {"fromCheck.execute(fromObj)", "toCheck.execute(toObj)", "byCheck.execute(byObj)"}) @@ -307,7 +309,7 @@ public final class SeqFunctions { @Cached("createIsMissingOrNumericNode()") IsMissingOrNumericNode fromCheck, @Cached("createIsMissingOrNumericNode()") IsMissingOrNumericNode toCheck, @Cached("createIsMissingOrNumericNode()") IsMissingOrNumericNode byCheck) { - return seqInt.execute(frame, fromObj, toObj, byObj, lengthOut, alongWith); + return seqInt.execute(frame, fromObj, toObj, byObj, lengthOut, alongWith, RMissing.instance); } /** @@ -320,9 +322,9 @@ public final class SeqFunctions { } } - @TypeSystemReference(RTypesFlatLayout.class) + @TypeSystemReference(RTypes.class) @RBuiltin(name = "seq_along", kind = PRIMITIVE, parameterNames = {"along.with"}, behavior = PURE) - public abstract static class SeqAlong extends RBuiltinNode { + public abstract static class SeqAlong extends RBuiltinNode.Arg1 { @Child private ClassHierarchyNode classHierarchyNode = ClassHierarchyNode.create(); static { @@ -343,7 +345,7 @@ public final class SeqFunctions { protected RIntSequence seq(VirtualFrame frame, Object value, @Cached("createLengthResultCast()") CastNode resultCast, @Cached("createLengthDispatcher()") RExplicitBaseEnvCallDispatcher dispatcher) { - int result = (Integer) resultCast.execute(dispatcher.call(frame, value)); + int result = (Integer) resultCast.doCast(dispatcher.call(frame, value)); return RDataFactory.createIntSequence(1, 1, result); } @@ -357,19 +359,14 @@ public final class SeqFunctions { } CastNode createLengthResultCast() { - // @formatter:off - return newCastBuilder().asIntegerVector(false, false, false). - defaultError(NO_CALLER, Message.NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED). - findFirst(). - mustBe(gte(0).and(notIntNA())). - buildCastNode(); - // @formatter:on + return newCastBuilder().defaultError(Message.NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED).asIntegerVector(false, false, false).findFirst().mustBe( + gte(0).and(notIntNA())).buildCastNode(); } } - @TypeSystemReference(RTypesFlatLayout.class) + @TypeSystemReference(RTypes.class) @RBuiltin(name = "seq_len", kind = PRIMITIVE, parameterNames = {"length.out"}, behavior = PURE) - public abstract static class SeqLen extends RBuiltinNode { + public abstract static class SeqLen extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(SeqLen.class); @@ -406,18 +403,17 @@ public final class SeqFunctions { * * N.B. javac gives error "cannot find symbol" on plain "@RBuiltin". */ - @TypeSystemReference(RTypesFlatLayout.class) + @SuppressWarnings("unused") @ImportStatic({AsRealNodeGen.class, SeqFunctions.class}) @com.oracle.truffle.r.runtime.builtins.RBuiltin(name = "seq.int", kind = PRIMITIVE, parameterNames = {"from", "to", "by", "length.out", "along.with", "..."}, dispatch = INTERNAL_GENERIC, genericName = "seq", behavior = PURE) - @SuppressWarnings("unused") - public abstract static class SeqInt extends RBuiltinNode { + public abstract static class SeqInt extends RBuiltinNode.Arg6 { private final BranchProfile error = BranchProfile.create(); private final boolean seqFastPath; /** * Used by {@link #getLength} guard. It would be good to cache this in the relevant - * specializations but it does not use {@link RTypesFlatLayout} and that causes an + * specializations but it does not use {@link RTypes} and that causes an * IllegalStateException (no parent). */ @Child private RLengthNode lengthNode = RLengthNode.create(); @@ -425,10 +421,12 @@ public final class SeqFunctions { private static final double FLT_EPSILON = 1.19209290e-7; static { - Casts.noCasts(SeqInt.class); + Casts casts = new Casts(SeqInt.class); + casts.arg("length.out").allowMissing().mapIf(nullValue(), missingConstant()); } - protected abstract Object execute(VirtualFrame frame, Object start, Object to, Object by, Object lengthOut, Object alongWith); + @Override + public abstract Object execute(VirtualFrame frame, Object start, Object to, Object by, Object lengthOut, Object alongWith, Object dotdotdot); protected SeqInt(boolean seqFastPath) { this.seqFastPath = seqFastPath; @@ -449,7 +447,7 @@ public final class SeqFunctions { // No matching args (special case) @Specialization - protected RIntSequence allMissing(RMissing from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith) { + protected RIntSequence allMissing(RMissing from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) { // GNU R allows this and returns 1 return RDataFactory.createIntSequence(1, 1, 1); } @@ -464,7 +462,7 @@ public final class SeqFunctions { * Irrespective of the R type, if the length is zero the result is an empty sequence. */ @Specialization(guards = {"!isMissing(from)", "getLength(frame, from) == 0"}) - protected RIntVector emptySeqFromOneArg(VirtualFrame frame, Object from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith) { + protected RIntVector emptySeqFromOneArg(VirtualFrame frame, Object from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) { return RDataFactory.createEmptyIntVector(); } @@ -475,7 +473,7 @@ public final class SeqFunctions { * but the value likely could not be coerced. */ @Specialization(guards = {"!isMissing(from)", "getLength(frame, from) > 1"}) - protected RIntSequence lenSeqFromOneArg(VirtualFrame frame, Object from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith) { + protected RIntSequence lenSeqFromOneArg(VirtualFrame frame, Object from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) { return RDataFactory.createIntSequence(1, 1, getLength(frame, from)); } @@ -483,7 +481,7 @@ public final class SeqFunctions { * A length-1 REAL. Return "1:(int) from" where from is positive integral */ @Specialization(guards = {"fromVec.getLength() == 1", "isPositiveIntegralDouble(fromVec.getDataAt(0))"}) - protected RAbstractVector seqFromOneArgIntDouble(RAbstractDoubleVector fromVec, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith) { + protected RAbstractVector seqFromOneArgIntDouble(RAbstractDoubleVector fromVec, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) { int len = (int) fromVec.getDataAt(0); return RDataFactory.createIntSequence(1, 1, len); } @@ -493,7 +491,7 @@ public final class SeqFunctions { * {@code seq(0.2)} is NOT the same as {@code seq(0.0)} (according to GNU R) */ @Specialization(guards = "fromVec.getLength() == 1") - protected RAbstractVector seqFromOneArgDouble(RAbstractDoubleVector fromVec, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith) { + protected RAbstractVector seqFromOneArgDouble(RAbstractDoubleVector fromVec, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) { double from = validateDoubleParam(fromVec.getDataAt(0), fromVec, "from"); int len = effectiveLength(1, from); return RDataFactory.createIntSequence(1, from > 0 ? 1 : -1, len); @@ -503,7 +501,7 @@ public final class SeqFunctions { * A length-1 INT. Return "1:from" (N.B. from may be negative) */ @Specialization(guards = "fromVec.getLength() == 1") - protected RIntSequence seqFromOneArgInt(RAbstractIntVector fromVec, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith) { + protected RIntSequence seqFromOneArgInt(RAbstractIntVector fromVec, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) { int from = validateIntParam(fromVec.getDataAt(0), "from"); int len = from > 0 ? from : 2 - from; return RDataFactory.createIntSequence(1, from > 0 ? 1 : -1, len); @@ -516,19 +514,10 @@ public final class SeqFunctions { * which would be incorrect as the result is different. */ @Specialization(guards = {"!isMissing(from)", "getLength(frame, from) == 1", "!isNumeric(from)"}) - protected RIntSequence seqFromOneArgObj(VirtualFrame frame, Object from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith) { + protected RIntSequence seqFromOneArgObj(VirtualFrame frame, Object from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) { return RDataFactory.createIntSequence(1, 1, 1); } - /** - * Treat {@code lengthOut==NULL} as {@link RMissing}. - */ - @Specialization - protected RAbstractVector seqLengthByMissing(VirtualFrame frame, Object from, Object to, Object by, RNull lengthOut, RMissing alongWith, - @Cached("createSeqInt()") SeqInt seqIntNodeRecursive) { - return (RAbstractVector) seqIntNodeRecursive.execute(frame, from, to, by, RMissing.instance, alongWith); - } - /* * seq(from,to) but either could be missing. "along.with" is missing and "length.out" is * missing (or NULL), and "by" (by) is missing. N.B. we are only interested in the cases @@ -541,6 +530,7 @@ public final class SeqFunctions { @Specialization(guards = "validDoubleParams(fromVec, toVec)") protected RAbstractVector seqLengthByMissingDouble(VirtualFrame frame, RAbstractDoubleVector fromVec, RAbstractDoubleVector toVec, RMissing by, RMissing lengthOut, RMissing alongWith, + Object dotdotdot, @Cached("createBinaryProfile()") ConditionProfile directionProfile) { double from = fromVec.getDataAt(0); double to = toVec.getDataAt(0); @@ -549,7 +539,7 @@ public final class SeqFunctions { } @Specialization(guards = "validIntParams(fromVec, toVec)") - protected RAbstractVector seqLengthByMissingInt(VirtualFrame frame, RAbstractIntVector fromVec, RAbstractIntVector toVec, RMissing by, RMissing lengthOut, RMissing alongWith, + protected RAbstractVector seqLengthByMissingInt(VirtualFrame frame, RAbstractIntVector fromVec, RAbstractIntVector toVec, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot, @Cached("createBinaryProfile()") ConditionProfile directionProfile) { int from = fromVec.getDataAt(0); int to = toVec.getDataAt(0); @@ -565,7 +555,7 @@ public final class SeqFunctions { * previous specializations. */ @Specialization(guards = {"!isMissing(toObj)"}) - protected RAbstractVector seqLengthByMissing(VirtualFrame frame, Object fromObj, Object toObj, RMissing by, RMissing lengthOut, RMissing alongWith, + protected RAbstractVector seqLengthByMissing(VirtualFrame frame, Object fromObj, Object toObj, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot, @Cached("create()") AsRealNode asRealFrom, @Cached("create()") AsRealNode asRealTo, @Cached("createBinaryProfile()") ConditionProfile directionProfile) { @@ -591,7 +581,7 @@ public final class SeqFunctions { */ @Specialization(guards = {"validDoubleParams(fromVec, toVec)", "!isMissing(byObj)"}) - protected Object seqLengthMissing(VirtualFrame frame, RAbstractDoubleVector fromVec, RAbstractDoubleVector toVec, Object byObj, RMissing lengthOut, RMissing alongWith, + protected Object seqLengthMissing(VirtualFrame frame, RAbstractDoubleVector fromVec, RAbstractDoubleVector toVec, Object byObj, RMissing lengthOut, RMissing alongWith, Object dotdotdot, @Cached("create()") AsRealNode asRealby) { validateLength(frame, byObj, "by"); double by = asRealby.execute(byObj); @@ -600,6 +590,7 @@ public final class SeqFunctions { @Specialization(guards = {"validIntParams(fromVec, toVec)", "validIntParam(byVec)", "byVec.getDataAt(0) != 0"}) protected RAbstractVector seqLengthMissing(VirtualFrame frame, RAbstractIntVector fromVec, RAbstractIntVector toVec, RAbstractIntVector byVec, RMissing lengthOut, RMissing alongWith, + Object dotdotdot, @Cached("createBinaryProfile()") ConditionProfile directionProfile) { int by = byVec.getDataAt(0); int from = fromVec.getDataAt(0); @@ -608,7 +599,7 @@ public final class SeqFunctions { if (directionProfile.profile(from < to)) { if (by < 0) { error.enter(); - throw RError.error(this, RError.Message.WRONG_SIGN_IN_BY); + throw error(RError.Message.WRONG_SIGN_IN_BY); } result = RDataFactory.createIntSequence(from, by, (to - from) / by + 1); } else { @@ -617,7 +608,7 @@ public final class SeqFunctions { } if (by > 0) { error.enter(); - throw RError.error(this, RError.Message.WRONG_SIGN_IN_BY); + throw error(RError.Message.WRONG_SIGN_IN_BY); } result = RDataFactory.createIntSequence(from, by, (from - to) / (-by) + 1); } @@ -628,7 +619,7 @@ public final class SeqFunctions { * See comment in {@link #seqLengthByMissing}. */ @Specialization(guards = {"!isMissing(byObj)"}) - protected Object seqLengthMissing(VirtualFrame frame, Object fromObj, Object toObj, Object byObj, RMissing lengthOut, RMissing alongWith, + protected Object seqLengthMissing(VirtualFrame frame, Object fromObj, Object toObj, Object byObj, RMissing lengthOut, RMissing alongWith, Object dotdotdot, @Cached("create()") AsRealNode asRealFrom, @Cached("create()") AsRealNode asRealTo, @Cached("create()") AsRealNode asRealby) { @@ -674,7 +665,7 @@ public final class SeqFunctions { } else { error.enter(); // This should go away in an upcoming GNU R release - throw RError.error(this, seqFastPath ? RError.Message.INVALID_TFB_SD : RError.Message.INVALID_TFB); + throw error(seqFastPath ? RError.Message.INVALID_TFB_SD : RError.Message.INVALID_TFB); } } double dd = Math.abs(del) / Math.max(Math.abs(to), Math.abs(from)); @@ -684,11 +675,11 @@ public final class SeqFunctions { } if (n > Integer.MAX_VALUE) { error.enter(); - throw RError.error(this, RError.Message.BY_TOO_SMALL); + throw error(RError.Message.BY_TOO_SMALL); } if (n < -FEPS) { error.enter(); - throw RError.error(this, RError.Message.WRONG_SIGN_IN_BY); + throw error(RError.Message.WRONG_SIGN_IN_BY); } RAbstractVector result; if (allInt) { @@ -724,7 +715,7 @@ public final class SeqFunctions { */ @Specialization(guards = "!isMissing(lengthOut)") - protected RAbstractVector seqJustLength(VirtualFrame frame, RMissing from, RMissing to, RMissing by, Object lengthOut, RMissing alongWith, + protected RAbstractVector seqJustLength(VirtualFrame frame, RMissing from, RMissing to, RMissing by, Object lengthOut, RMissing alongWith, Object dotdotdot, @Cached("create()") AsRealNode asRealLen) { int n = checkLength(frame, lengthOut, asRealLen); return n == 0 ? RDataFactory.createEmptyIntVector() : RDataFactory.createIntSequence(1, 1, n); @@ -733,7 +724,7 @@ public final class SeqFunctions { // seq(along,with=) @Specialization(guards = "!isMissing(alongWith)") - protected RAbstractVector seqFromJustAlong(VirtualFrame frame, RMissing from, RMissing to, RMissing by, RMissing lengthOut, Object alongWith) { + protected RAbstractVector seqFromJustAlong(VirtualFrame frame, RMissing from, RMissing to, RMissing by, RMissing lengthOut, Object alongWith, Object dotdotdot) { int len = getLength(frame, alongWith); return len == 0 ? RDataFactory.createEmptyIntVector() : RDataFactory.createIntSequence(1, 1, len); } @@ -759,7 +750,7 @@ public final class SeqFunctions { * and often use "1" where "1L" is more appropriate). */ - @TypeSystemReference(RTypesFlatLayout.class) + @TypeSystemReference(RTypes.class) public abstract static class IsIntegralNumericNode extends Node { private final boolean checkLength; @@ -807,7 +798,7 @@ public final class SeqFunctions { // common idiom @Specialization(guards = {"fromCheck.execute(fromObj)", "lengthCheck.execute(lengthOut)"}) - protected RAbstractVector seqWithFromLengthIntegralNumeric(VirtualFrame frame, Object fromObj, RMissing toObj, RMissing byObj, Object lengthOut, RMissing alongWith, + protected RAbstractVector seqWithFromLengthIntegralNumeric(VirtualFrame frame, Object fromObj, RMissing toObj, RMissing byObj, Object lengthOut, RMissing alongWith, Object dotdotdot, @Cached("createGetIntegralNumericNode()") GetIntegralNumericNode getIntegralNumericNode, @Cached("createIsIntegralNumericNodeNoLengthCheck()") IsIntegralNumericNode fromCheck, @Cached("createIsIntegralNumericNodeLengthCheck()") IsIntegralNumericNode lengthCheck) { @@ -822,7 +813,7 @@ public final class SeqFunctions { // "by" missing @Specialization(guards = {"oneNotMissing(alongWith, lengthOut)", "oneNotMissing(fromObj, toObj)"}) - protected RAbstractVector seqWithLength(VirtualFrame frame, Object fromObj, Object toObj, RMissing byObj, Object lengthOut, Object alongWith, + protected RAbstractVector seqWithLength(VirtualFrame frame, Object fromObj, Object toObj, RMissing byObj, Object lengthOut, Object alongWith, Object dotdotdot, @Cached("create()") AsRealNode asRealFrom, @Cached("create()") AsRealNode asRealTo, @Cached("create()") AsRealNode asRealLen) { @@ -876,7 +867,7 @@ public final class SeqFunctions { // "to" missing @Specialization(guards = {"oneNotMissing(alongWith, lengthOut)", "oneNotMissing(fromObj, byObj)"}) - protected RAbstractVector seqWithLength(VirtualFrame frame, Object fromObj, RMissing toObj, Object byObj, Object lengthOut, Object alongWith, + protected RAbstractVector seqWithLength(VirtualFrame frame, Object fromObj, RMissing toObj, Object byObj, Object lengthOut, Object alongWith, Object dotdotdot, @Cached("create()") AsRealNode asRealFrom, @Cached("create()") AsRealNode asRealby, @Cached("create()") AsRealNode asRealLen) { @@ -903,7 +894,7 @@ public final class SeqFunctions { // "from" missing @Specialization(guards = {"oneNotMissing(alongWith, lengthOut)", "oneNotMissing(toObj, byObj)"}) - protected RAbstractVector seqWithLength(VirtualFrame frame, RMissing fromObj, Object toObj, Object byObj, Object lengthOut, Object alongWith, + protected RAbstractVector seqWithLength(VirtualFrame frame, RMissing fromObj, Object toObj, Object byObj, Object lengthOut, Object alongWith, Object dotdotdot, @Cached("create()") AsRealNode asRealTo, @Cached("create()") AsRealNode asRealby, @Cached("create()") AsRealNode asRealLen) { @@ -924,9 +915,9 @@ public final class SeqFunctions { } @Fallback - protected RAbstractVector seqFallback(VirtualFrame frame, Object fromObj, Object toObj, Object byObj, Object lengthOut, Object alongWith) { + protected RAbstractVector seqFallback(VirtualFrame frame, Object fromObj, Object toObj, Object byObj, Object lengthOut, Object alongWith, Object dotdotdot) { error.enter(); - throw RError.error(this, RError.Message.TOO_MANY_ARGS); + throw error(RError.Message.TOO_MANY_ARGS); } // Guard methods @@ -977,7 +968,7 @@ public final class SeqFunctions { private int validateIntParam(int v, String vName) { if (RRuntime.isNA(v)) { error.enter(); - throw RError.error(this, RError.Message.CANNOT_BE_INVALID, vName); + throw error(RError.Message.CANNOT_BE_INVALID, vName); } return v; } @@ -990,7 +981,7 @@ public final class SeqFunctions { if (vObj != RMissing.instance) { if (!isFinite(v)) { error.enter(); - throw RError.error(this, RError.Message.CANNOT_BE_INVALID, vName); + throw error(RError.Message.CANNOT_BE_INVALID, vName); } } return v; @@ -1003,7 +994,7 @@ public final class SeqFunctions { if (obj != RMissing.instance) { if (getLength(frame, obj) != 1) { error.enter(); - throw RError.error(this, RError.Message.MUST_BE_SCALAR, vName); + throw error(RError.Message.MUST_BE_SCALAR, vName); } } } @@ -1012,10 +1003,10 @@ public final class SeqFunctions { double len = asRealLen.execute(lengthOut); if (RRuntime.isNAorNaN(len) || len <= -0.5) { error.enter(); - throw RError.error(this, seqFastPath ? RError.Message.MUST_BE_POSITIVE_SD : RError.Message.MUST_BE_POSITIVE, seqFastPath ? "length" : "length.out"); + throw error(seqFastPath ? RError.Message.MUST_BE_POSITIVE_SD : RError.Message.MUST_BE_POSITIVE, seqFastPath ? "length" : "length.out"); } if (getLength(frame, lengthOut) != 1) { - RError.warning(this, RError.Message.FIRST_ELEMENT_USED, "length.out"); + warning(RError.Message.FIRST_ELEMENT_USED, "length.out"); } return (int) Math.ceil(len); } @@ -1047,7 +1038,7 @@ public final class SeqFunctions { double r = Math.abs(to - from); if (r > Integer.MAX_VALUE) { error.enter(); - throw RError.error(this, RError.Message.TOO_LONG_VECTOR); + throw error(RError.Message.TOO_LONG_VECTOR); } int length = (int) (r + 1 + FLT_EPSILON); return length; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java index 82f063958e5b04d6b10fd0637d0f6dc5f43146cc..8d1d96657307c3c77269954db15558cf88c23a05 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java @@ -35,6 +35,7 @@ import java.io.IOException; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; @@ -46,52 +47,51 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; public class SerializeFunctions { - public abstract static class Adapter extends RBuiltinNode { - @TruffleBoundary - protected Object doUnserializeFromConnBase(int connIndex, @SuppressWarnings("unused") REnvironment refhook) { - try (RConnection openConn = RConnection.fromIndex(connIndex).forceOpen("rb")) { - if (!openConn.canRead()) { - throw RError.error(this, RError.Message.CONNECTION_NOT_OPEN_READ); - } - return RSerialize.unserialize(openConn); - } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); + @TruffleBoundary + protected static Object doUnserializeFromConnBase(RBaseNode node, int connIndex, @SuppressWarnings("unused") REnvironment refhook) { + try (RConnection openConn = RConnection.fromIndex(connIndex).forceOpen("rb")) { + if (!openConn.canRead()) { + throw node.error(RError.Message.CONNECTION_NOT_OPEN_READ); } + return RSerialize.unserialize(openConn); + } catch (IOException ex) { + throw node.error(RError.Message.GENERIC, ex.getMessage()); } + } + + @TruffleBoundary + protected static Object doUnserializeFromRaw(RAbstractRawVector data, @SuppressWarnings("unused") REnvironment refhook) { + return RSerialize.unserialize(data); + } - @TruffleBoundary - protected Object doUnserializeFromRaw(RAbstractRawVector data, @SuppressWarnings("unused") REnvironment refhook) { - return RSerialize.unserialize(data); - } - - @TruffleBoundary - protected Object doSerializeToConnBase(Object object, int connIndex, int type, @SuppressWarnings("unused") byte xdrLogical, @SuppressWarnings("unused") RNull version, - @SuppressWarnings("unused") RNull refhook) { - // xdr is only relevant if ascii is false - try (RConnection openConn = RConnection.fromIndex(connIndex).forceOpen(type != RSerialize.XDR ? "wt" : "wb")) { - if (!openConn.canWrite()) { - throw RError.error(this, RError.Message.CONNECTION_NOT_OPEN_WRITE); - } - if (type == RSerialize.XDR && openConn.isTextMode()) { - throw RError.error(this, RError.Message.BINARY_CONNECTION_REQUIRED); - } - RSerialize.serialize(openConn, object, type, RSerialize.DEFAULT_VERSION, null); - return RNull.instance; - } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); + @TruffleBoundary + protected static Object doSerializeToConnBase(RBaseNode node, Object object, int connIndex, int type, @SuppressWarnings("unused") byte xdrLogical, @SuppressWarnings("unused") RNull version, + @SuppressWarnings("unused") RNull refhook) { + // xdr is only relevant if ascii is false + try (RConnection openConn = RConnection.fromIndex(connIndex).forceOpen(type != RSerialize.XDR ? "wt" : "wb")) { + if (!openConn.canWrite()) { + throw node.error(RError.Message.CONNECTION_NOT_OPEN_WRITE); } + if (type == RSerialize.XDR && openConn.isTextMode()) { + throw node.error(RError.Message.BINARY_CONNECTION_REQUIRED); + } + RSerialize.serialize(openConn, object, type, RSerialize.DEFAULT_VERSION, null); + return RNull.instance; + } catch (IOException ex) { + throw node.error(RError.Message.GENERIC, ex.getMessage()); } + } - protected static void connection(Casts casts) { - casts.arg("con").mustBe(integerValue()).asIntegerVector().findFirst(); - } + protected static void connection(Casts casts) { + casts.arg("con").mustBe(integerValue()).asIntegerVector().findFirst(); } @RBuiltin(name = "unserializeFromConn", kind = INTERNAL, parameterNames = {"con", "refhook"}, behavior = IO) - public abstract static class UnserializeFromConn extends Adapter { + public abstract static class UnserializeFromConn extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(UnserializeFromConn.class); @@ -100,24 +100,26 @@ public class SerializeFunctions { @Specialization protected Object doUnserializeFromConn(int conn, @SuppressWarnings("unused") RNull refhook) { - return doUnserializeFromConnBase(conn, null); + return doUnserializeFromConnBase(this, conn, null); } @Specialization protected Object doUnserializeFromConn(int conn, @SuppressWarnings("unused") REnvironment refhook) { // TODO figure out what this really means? - return doUnserializeFromConnBase(conn, null); + return doUnserializeFromConnBase(this, conn, null); } } @RBuiltin(name = "serializeToConn", visibility = OFF, kind = INTERNAL, parameterNames = {"object", "con", "ascii", "version", "refhook"}, behavior = IO) - public abstract static class SerializeToConn extends Adapter { + public abstract static class SerializeToConn extends RBuiltinNode.Arg5 { static { Casts casts = new Casts(SerializeToConn.class); + casts.arg("object").mustNotBeMissing(); connection(casts); - casts.arg("ascii").mustBe(logicalValue(), RError.Message.ASCII_NOT_LOGICAL); - casts.arg("version").allowNull().mustBe(integerValue()); + casts.arg("ascii").mustBe(logicalValue(), RError.Message.ASCII_NOT_LOGICAL).asLogicalVector().findFirst(); + casts.arg("version").allowNull().mustBe(integerValue()).asIntegerVector().findFirst(); + casts.arg("refhook").mustNotBeMissing(); } @Specialization @@ -130,12 +132,19 @@ public class SerializeFunctions { } else { type = RSerialize.XDR; } - return doSerializeToConnBase(object, conn, type, RRuntime.LOGICAL_NA, version, refhook); + return doSerializeToConnBase(this, object, conn, type, RRuntime.LOGICAL_NA, version, refhook); + } + + @SuppressWarnings("unused") + @Specialization + protected Object doSerializeToConn(Object object, int conn, byte asciiLogical, int version, Object refhook) { + // TODO: implement "version" support + throw RError.error(this, RError.Message.UNIMPLEMENTED_ARG_TYPE, 4); } } @RBuiltin(name = "unserialize", kind = INTERNAL, parameterNames = {"con", "refhook"}, behavior = IO) - public abstract static class Unserialize extends Adapter { + public abstract static class Unserialize extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(Unserialize.class); @@ -145,7 +154,7 @@ public class SerializeFunctions { @Specialization protected Object unSerialize(int conn, @SuppressWarnings("unused") RNull refhook) { - return doUnserializeFromConnBase(conn, null); + return doUnserializeFromConnBase(this, conn, null); } @Specialization @@ -155,7 +164,7 @@ public class SerializeFunctions { } @RBuiltin(name = "serialize", kind = INTERNAL, parameterNames = {"object", "con", "type", "version", "refhook"}, behavior = IO) - public abstract static class Serialize extends Adapter { + public abstract static class Serialize extends RBuiltinNode.Arg5 { static { Casts casts = new Casts(Serialize.class); @@ -165,7 +174,7 @@ public class SerializeFunctions { @Specialization protected Object serialize(Object object, int conn, int type, RNull version, RNull refhook) { - return doSerializeToConnBase(object, conn, type, RRuntime.LOGICAL_NA, version, refhook); + return doSerializeToConnBase(this, object, conn, type, RRuntime.LOGICAL_NA, version, refhook); } @SuppressWarnings("unused") @@ -177,7 +186,7 @@ public class SerializeFunctions { } @RBuiltin(name = "serializeb", kind = INTERNAL, parameterNames = {"object", "con", "xdr", "version", "refhook"}, behavior = IO) - public abstract static class SerializeB extends Adapter { + public abstract static class SerializeB extends RBuiltinNode.Arg5 { static { Casts casts = new Casts(SerializeB.class); @@ -190,7 +199,7 @@ public class SerializeFunctions { if (!RRuntime.fromLogical(xdrLogical)) { throw RError.nyi(this, "xdr==FALSE"); } - return doSerializeToConnBase(object, conn, RRuntime.LOGICAL_FALSE, xdrLogical, version, refhook); + return doSerializeToConnBase(this, object, conn, RRuntime.LOGICAL_FALSE, xdrLogical, version, refhook); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java index 49a67b4f48980a143aad02f3f03e8ec02e465df8..bc74b10deb46f6f2f428c9b172a82f136a539676 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java @@ -40,16 +40,16 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RSequence; @RBuiltin(name = "setS4Object", kind = INTERNAL, parameterNames = {"object", "flag", "complete"}, behavior = PURE) -public abstract class SetS4Object extends RBuiltinNode { +public abstract class SetS4Object extends RBuiltinNode.Arg3 { @Child private AsS4 asS4 = AsS4NodeGen.create(); static { Casts casts = new Casts(SetS4Object.class); - casts.arg("object").asAttributable(true, true, true); - casts.arg("flag").asLogicalVector().mustBe(singleElement(), RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "flag").findFirst().map(toBoolean()); + casts.arg("object").mustNotBeMissing().asAttributable(true, true, true); + casts.arg("flag").asLogicalVector().mustBe(singleElement(), RError.Message.INVALID_ARGUMENT, "flag").findFirst().map(toBoolean()); // "complete" can be a vector, unlike "flag" - casts.arg("complete").asIntegerVector().findFirst(RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "complete"); + casts.arg("complete").asIntegerVector().findFirst(RError.Message.INVALID_ARGUMENT, "complete"); } @Specialization @@ -61,7 +61,7 @@ public abstract class SetS4Object extends RBuiltinNode { boolean wasS4 = RContext.getInstance().isNullS4Object(); RContext.getInstance().setNullS4Object(false); if (wasS4) { - throw RError.error(this, RError.Message.GENERIC, "object of class \"NULL\" does not correspond to a valid S3 object"); + throw error(RError.Message.GENERIC, "object of class \"NULL\" does not correspond to a valid S3 object"); } } return object; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetTimeLimit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetTimeLimit.java index 1b89fd845d9dbf51868d1edbe4d16746ce729a44..175bf4347b1f4dde19997b0aeb528b6c4c7c4e21 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetTimeLimit.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetTimeLimit.java @@ -33,7 +33,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RNull; @RBuiltin(name = "setTimeLimit", kind = INTERNAL, parameterNames = {"cpu", "elapsed", "transient"}, visibility = OFF, behavior = COMPLEX) -public abstract class SetTimeLimit extends RBuiltinNode { +public abstract class SetTimeLimit extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(SetTimeLimit.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java index 4c4abf4a6babb76967a8375e9285be5cee6c26e3..92ca9352eafb946d049bb19e5cbcd3defa9289bd 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java @@ -24,7 +24,6 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; -import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; import static com.oracle.truffle.r.runtime.RError.Message.CHAR_ARGUMENT; import static com.oracle.truffle.r.runtime.RVisibility.OFF; import static com.oracle.truffle.r.runtime.builtins.RBehavior.IO; @@ -40,11 +39,11 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.ffi.BaseRFFI; @RBuiltin(name = "setwd", visibility = OFF, kind = INTERNAL, parameterNames = "path", behavior = IO) -public abstract class Setwd extends RBuiltinNode { +public abstract class Setwd extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(Setwd.class); - casts.arg("path").defaultError(SHOW_CALLER, CHAR_ARGUMENT).mustBe(stringValue()).asStringVector().mustBe(notEmpty()).findFirst(); + casts.arg("path").defaultError(CHAR_ARGUMENT).mustBe(stringValue()).asStringVector().mustBe(notEmpty()).findFirst(); } @Specialization @@ -56,7 +55,7 @@ public abstract class Setwd extends RBuiltinNode { String nwd = Utils.tildeExpand(path); int rc = setwdNode.execute(nwd); if (rc != 0) { - throw RError.error(this, RError.Message.CANNOT_CHANGE_DIRECTORY); + throw error(RError.Message.CANNOT_CHANGE_DIRECTORY); } else { String nwdAbs = getwdNode.execute(); Utils.updateCurwd(nwdAbs); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ShortRowNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ShortRowNames.java index eed5de7dd1ead62987cd2954a548cc3fbb369516..9d9e87d1c0e3cc7a032311959d65dec6d46c54e4 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ShortRowNames.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ShortRowNames.java @@ -42,10 +42,9 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.env.REnvironment; @RBuiltin(name = "shortRowNames", kind = INTERNAL, parameterNames = {"x", "type"}, behavior = PURE) -public abstract class ShortRowNames extends RBuiltinNode { +public abstract class ShortRowNames extends RBuiltinNode.Arg2 { private final BranchProfile naValueMet = BranchProfile.create(); - private final BranchProfile errorProfile = BranchProfile.create(); private final ValueProfile operandTypeProfile = ValueProfile.createClassProfile(); @Child private GetRowNamesAttributeNode getRowNamesNode = GetRowNamesAttributeNode.create(); @@ -98,8 +97,7 @@ public abstract class ShortRowNames extends RBuiltinNode { } else if (rowNames instanceof RAbstractContainer) { return ((RAbstractContainer) rowNames).getLength(); } else { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "type"); + throw error(RError.Message.INVALID_ARGUMENT, "type"); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Signif.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Signif.java index 5c3afc71a88a397a4839c202e2362c4c5ed9fcb3..1ef56ebc6b17357b39cb72c0b879006c7038d680 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Signif.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Signif.java @@ -55,7 +55,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "signif", kind = PRIMITIVE, parameterNames = {"x", "digits"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) -public abstract class Signif extends RBuiltinNode { +public abstract class Signif extends RBuiltinNode.Arg2 { @Override public Object[] getDefaultParameterValues() { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SinkFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SinkFunctions.java index 9ae7473c5fd527622e26ee63b9dbc4cb88343566..313a824464980e11457c7a1f626586f9949367dd 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SinkFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SinkFunctions.java @@ -41,14 +41,14 @@ import com.oracle.truffle.r.runtime.data.RNull; public class SinkFunctions { @RBuiltin(name = "sink", visibility = OFF, kind = INTERNAL, parameterNames = {"file", "closeOnExit", "type", "split"}, behavior = IO) - public abstract static class Sink extends RBuiltinNode { + public abstract static class Sink extends RBuiltinNode.Arg4 { static { Casts casts = new Casts(Sink.class); casts.arg("file").mustBe(integerValue()).asIntegerVector().findFirst(); - casts.arg("closeOnExit").asLogicalVector().findFirst().notNA().map(toBoolean()); - casts.arg("type").asLogicalVector().findFirst().notNA().map(toBoolean()); - casts.arg("split").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("closeOnExit").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); + casts.arg("type").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); + casts.arg("split").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } @Specialization @@ -62,7 +62,7 @@ public class SinkFunctions { try { StdConnections.popDivertOut(); } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); + throw error(RError.Message.GENERIC, ex.getMessage()); } } else { RConnection conn = RConnection.fromIndex(file); @@ -77,11 +77,11 @@ public class SinkFunctions { } @RBuiltin(name = "sink.number", kind = INTERNAL, parameterNames = {"type"}, behavior = IO) - public abstract static class SinkNumber extends RBuiltinNode { + public abstract static class SinkNumber extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(SinkNumber.class); - casts.arg("type").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("type").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java index b785bc5ddd4cfc6dc4d3d34e8c540c729dc1a3fb..98c7e6420098a0b05fac67463bd3adf6275a0cf2 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java @@ -26,6 +26,7 @@ import com.oracle.truffle.r.nodes.access.ConstantNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.WrapArgumentNode; +import com.oracle.truffle.r.nodes.function.opt.UpdateShareableChildValueNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -33,8 +34,9 @@ import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RSymbol; @RBuiltin(name = "@", kind = PRIMITIVE, parameterNames = {"", ""}, nonEvalArgs = 1, behavior = COMPLEX) -public abstract class Slot extends RBuiltinNode { +public abstract class Slot extends RBuiltinNode.Arg2 { + @Child private UpdateShareableChildValueNode sharedAttrUpdate = UpdateShareableChildValueNode.create(); @Child private AccessSlotNode accessSlotNode = AccessSlotNodeGen.create(true); static { @@ -61,7 +63,7 @@ public abstract class Slot extends RBuiltinNode { } } CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.GENERIC, "invalid type or length for slot name"); + throw error(RError.Message.GENERIC, "invalid type or length for slot name"); } @Specialization @@ -69,6 +71,10 @@ public abstract class Slot extends RBuiltinNode { @Cached("createClassProfile()") ValueProfile nameObjProfile) { String name = getName(nameObjProfile.profile(nameObj)); assert Utils.isInterned(name); - return accessSlotNode.executeAccess(object, name); + Object result = accessSlotNode.executeAccess(object, name); + + // since we give the slot away, we probably have to increase the refCount + sharedAttrUpdate.execute(object, result); + return result; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java index 7ae1a1ce6eca3d86d4648f695d9b339797771d41..1cbef88f119a988783ab30f87c7841653f9714b4 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java @@ -23,11 +23,17 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.rawValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; -import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; import static com.oracle.truffle.r.runtime.RError.Message.INVALID_LOGICAL; +import static com.oracle.truffle.r.runtime.RError.Message.NOT_NUMERIC_VECTOR; import static com.oracle.truffle.r.runtime.RError.Message.ONLY_ATOMIC_CAN_BE_SORTED; +import static com.oracle.truffle.r.runtime.RError.Message.RAW_SORT; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -36,6 +42,7 @@ import java.util.Collections; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; @@ -47,8 +54,10 @@ import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RLogicalVector; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; 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; @@ -58,87 +67,86 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; */ public class SortFunctions { - private abstract static class Adapter extends RBuiltinNode { - protected static void addCastForX(Casts casts) { - casts.arg("x").allowNull().mustBe(abstractVectorValue(), SHOW_CALLER, ONLY_ATOMIC_CAN_BE_SORTED); - } + protected static void addCastForX(Casts casts) { + casts.arg("x").allowNull().mustBe(rawValue().not(), RAW_SORT).mustBe(instanceOf(RAbstractListVector.class).not(), ONLY_ATOMIC_CAN_BE_SORTED).mustBe( + abstractVectorValue(), ONLY_ATOMIC_CAN_BE_SORTED); + } - protected static void addCastForDecreasing(Casts casts) { - casts.arg("decreasing").defaultError(SHOW_CALLER, INVALID_LOGICAL, "decreasing").mustBe(numericValue()).asLogicalVector().findFirst().map(toBoolean()); - } + protected static void addCastForDecreasing(Casts casts) { + casts.arg("decreasing").defaultError(INVALID_LOGICAL, "decreasing").mustBe(numericValue()).asLogicalVector().findFirst().map(toBoolean()); + } - @TruffleBoundary - private static double[] sort(double[] data, boolean decreasing) { - // no reverse comparator for primitives - Arrays.parallelSort(data); - if (decreasing) { - int len = data.length; - for (int i = len / 2 - 1; i >= 0; i--) { - double temp = data[i]; - data[i] = data[len - i - 1]; - data[len - i - 1] = temp; - } + @TruffleBoundary + private static double[] sort(double[] data, boolean decreasing) { + // no reverse comparator for primitives + Arrays.parallelSort(data); + if (decreasing) { + int len = data.length; + for (int i = len / 2 - 1; i >= 0; i--) { + double temp = data[i]; + data[i] = data[len - i - 1]; + data[len - i - 1] = temp; } - return data; } + return data; + } - @TruffleBoundary - private static int[] sort(int[] data, boolean decreasing) { - Arrays.parallelSort(data); - if (decreasing) { - int len = data.length; - for (int i = len / 2 - 1; i >= 0; i--) { - int temp = data[i]; - data[i] = data[len - i - 1]; - data[len - i - 1] = temp; - } + @TruffleBoundary + private static int[] sort(int[] data, boolean decreasing) { + Arrays.parallelSort(data); + if (decreasing) { + int len = data.length; + for (int i = len / 2 - 1; i >= 0; i--) { + int temp = data[i]; + data[i] = data[len - i - 1]; + data[len - i - 1] = temp; } - return data; } + return data; + } - @TruffleBoundary - private static byte[] sort(byte[] data, boolean decreasing) { - Arrays.parallelSort(data); - if (decreasing) { - int len = data.length; - for (int i = len / 2 - 1; i >= 0; i--) { - byte temp = data[i]; - data[i] = data[len - i - 1]; - data[len - i - 1] = temp; - } + @TruffleBoundary + private static byte[] sort(byte[] data, boolean decreasing) { + Arrays.parallelSort(data); + if (decreasing) { + int len = data.length; + for (int i = len / 2 - 1; i >= 0; i--) { + byte temp = data[i]; + data[i] = data[len - i - 1]; + data[len - i - 1] = temp; } - return data; } + return data; + } - @TruffleBoundary - private static String[] sort(String[] data, boolean decreasing) { - if (decreasing) { - Arrays.parallelSort(data, Collections.reverseOrder()); - } else { - Arrays.parallelSort(data); - } - return data; + @TruffleBoundary + private static String[] sort(String[] data, boolean decreasing) { + if (decreasing) { + Arrays.parallelSort(data, Collections.reverseOrder()); + } else { + Arrays.parallelSort(data); } + return data; + } - protected RDoubleVector jdkSort(RAbstractDoubleVector vec, boolean decreasing) { - double[] data = vec.materialize().getDataCopy(); - return RDataFactory.createDoubleVector(sort(data, decreasing), vec.isComplete()); - } + protected static RDoubleVector jdkSort(RAbstractDoubleVector vec, boolean decreasing) { + double[] data = vec.materialize().getDataCopy(); + return RDataFactory.createDoubleVector(sort(data, decreasing), vec.isComplete()); + } - protected RIntVector jdkSort(RAbstractIntVector vec, boolean decreasing) { - int[] data = vec.materialize().getDataCopy(); - return RDataFactory.createIntVector(sort(data, decreasing), vec.isComplete()); - } + protected static RIntVector jdkSort(RAbstractIntVector vec, boolean decreasing) { + int[] data = vec.materialize().getDataCopy(); + return RDataFactory.createIntVector(sort(data, decreasing), vec.isComplete()); + } - protected RStringVector jdkSort(RAbstractStringVector vec, boolean decreasing) { - String[] data = vec.materialize().getDataCopy(); - return RDataFactory.createStringVector(sort(data, decreasing), vec.isComplete()); - } + protected static RStringVector jdkSort(RAbstractStringVector vec, boolean decreasing) { + String[] data = vec.materialize().getDataCopy(); + return RDataFactory.createStringVector(sort(data, decreasing), vec.isComplete()); + } - protected RLogicalVector jdkSort(RAbstractLogicalVector vec, boolean decreasing) { - byte[] data = vec.materialize().getDataCopy(); - return RDataFactory.createLogicalVector(sort(data, decreasing), vec.isComplete()); - } + protected static RLogicalVector jdkSort(RAbstractLogicalVector vec, boolean decreasing) { + byte[] data = vec.materialize().getDataCopy(); + return RDataFactory.createLogicalVector(sort(data, decreasing), vec.isComplete()); } /** @@ -149,7 +157,7 @@ public class SortFunctions { * N.B. The R code strips out {@code NA} and {@code NaN} values before calling the builtin. */ @RBuiltin(name = "sort", kind = INTERNAL, parameterNames = {"x", "decreasing"}, behavior = PURE) - public abstract static class Sort extends Adapter { + public abstract static class Sort extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(Sort.class); @@ -176,15 +184,27 @@ public class SortFunctions { protected RLogicalVector sort(RAbstractLogicalVector vec, boolean decreasing) { return jdkSort(vec, decreasing); } + + @Specialization + protected RLogicalVector sort(@SuppressWarnings("unused") RAbstractComplexVector vec, @SuppressWarnings("unused") boolean decreasing) { + // TODO: implement complex sort + throw RError.error(this, RError.Message.UNIMPLEMENTED_ARG_TYPE, 1); + } + + @Specialization + protected RNull sort(@SuppressWarnings("unused") RNull vec, @SuppressWarnings("unused") boolean decreasing) { + return RNull.instance; + } + } @RBuiltin(name = "qsort", kind = INTERNAL, parameterNames = {"x", "decreasing"}, behavior = PURE) - public abstract static class QSort extends Adapter { + public abstract static class QSort extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(QSort.class); - addCastForX(casts); - addCastForDecreasing(casts); + casts.arg("x").defaultError(NOT_NUMERIC_VECTOR).mustBe(instanceOf(RAbstractListVector.class).not()).mustBe(integerValue().or(doubleValue())); + casts.arg("decreasing").mapIf(numericValue().not(), constant(RRuntime.LOGICAL_TRUE)).asLogicalVector().findFirst().map(toBoolean()); } @Specialization @@ -199,7 +219,7 @@ public class SortFunctions { } @RBuiltin(name = "psort", kind = INTERNAL, parameterNames = {"x", "partial"}, behavior = PURE) - public abstract static class PartialSort extends Adapter { + public abstract static class PartialSort extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(PartialSort.class); @@ -229,6 +249,17 @@ public class SortFunctions { protected RLogicalVector sort(RAbstractLogicalVector vec, Object partial) { return jdkSort(vec, false); } + + @SuppressWarnings("unused") + @Specialization + protected RLogicalVector sort(RAbstractComplexVector vec, Object partial) { + throw RError.error(this, RError.Message.UNIMPLEMENTED_ARG_TYPE, 1); // [TODO] implement + } + + @Specialization + protected RNull sort(@SuppressWarnings("unused") RNull vec, @SuppressWarnings("unused") Object partial) { + return RNull.instance; + } } /** @@ -238,13 +269,13 @@ public class SortFunctions { * now we delegate to {@code order} and do not implement the {@code retgrp} argument. */ @RBuiltin(name = "radixsort", kind = INTERNAL, parameterNames = {"na.last", "decreasing", "retgrp", "sortstr", "..."}, behavior = PURE) - public abstract static class RadixSort extends Adapter { + public abstract static class RadixSort extends RBuiltinNode.Arg5 { @Child private Order orderNode = OrderNodeGen.create(); static { Casts casts = new Casts(RadixSort.class); casts.arg("na.last").asLogicalVector().findFirst(); - casts.arg("decreasing").mustBe(numericValue(), SHOW_CALLER, INVALID_LOGICAL, "decreasing").asLogicalVector(); + casts.arg("decreasing").mustBe(numericValue(), INVALID_LOGICAL, "decreasing").asLogicalVector(); casts.arg("retgrp").asLogicalVector().findFirst().map(toBoolean()); casts.arg("sortstr").asLogicalVector().findFirst().map(toBoolean()); } @@ -262,7 +293,7 @@ public class SortFunctions { return RNull.instance; } if (nargs != decreasingVec.getLength()) { - throw RError.error(this, RError.Message.RADIX_SORT_DEC_MATCH); + throw error(RError.Message.RADIX_SORT_DEC_MATCH); } /* * Order takes a single decreasing argument that applies to all the vectors. We @@ -274,7 +305,7 @@ public class SortFunctions { for (int i = 0; i < nargs; i++) { byte db = decreasingVec.getDataAt(i); if (RRuntime.isNA(db)) { - throw RError.error(this, RError.Message.RADIX_SORT_DEC_NOT_LOGICAL); + throw error(RError.Message.RADIX_SORT_DEC_NOT_LOGICAL); } if (lastdb != RRuntime.LOGICAL_NA && db != lastdb) { throw RError.nyi(this, "radixsort: args > 1 with differing 'decreasing' values not implemented"); 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 b43d2e7fc99f702010a8b8dc62359b7caa97faad..8a5446c3d6af500002450e0b5686860bd2c4f872 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 @@ -49,7 +49,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; * identical except for the argument type. */ @RBuiltin(name = "split", kind = INTERNAL, parameterNames = {"x", "f"}, behavior = PURE) -public abstract class Split extends RBuiltinNode { +public abstract class Split extends RBuiltinNode.Arg2 { @Child private RFactorNodes.GetLevels getLevelNode = new RFactorNodes.GetLevels(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java index 1a47d84f964031ec045edef55899b04c91a727c1..fcadf58d328e1fd882f6721e5453e36135a1b4b0 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java @@ -46,7 +46,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "sprintf", kind = INTERNAL, parameterNames = {"fmt", "..."}, behavior = PURE) -public abstract class Sprintf extends RBuiltinNode { +public abstract class Sprintf extends RBuiltinNode.Arg2 { static { Casts.noCasts(Sprintf.class); @@ -114,7 +114,7 @@ public abstract class Sprintf extends RBuiltinNode { if (Math.floor(x) == x) { return format(fmt, (long) x); } - throw RError.error(this, RError.Message.INVALID_FORMAT_DOUBLE, fmt); + throw error(RError.Message.INVALID_FORMAT_DOUBLE, fmt); } return format(fmt, x); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java index 9ca4d012ee7ee4ffb39ff638f80dd06d19859e5c..0334382ddc1d606ea1bbd9dfb1ba213dda04c6cc 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java @@ -55,7 +55,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment; // transcribed from /src/library/methods/src/methods_list_dispatch.c (R_dispatch_generic function) @RBuiltin(name = "standardGeneric", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"f", "fdef"}, behavior = COMPLEX) -public abstract class StandardGeneric extends RBuiltinNode { +public abstract class StandardGeneric extends RBuiltinNode.Arg2 { // TODO: for now, we always go through generic dispatch @@ -67,12 +67,8 @@ public abstract class StandardGeneric extends RBuiltinNode { @Child private CollectGenericArgumentsNode collectArgumentsNode; @Child private DispatchGeneric dispatchGeneric = DispatchGenericNodeGen.create(); - @Child private CastNode castIntScalar; - @Child private CastNode castStringScalar; - { - castIntScalar = newCastBuilder().asIntegerVector().findFirst(RRuntime.INT_NA).buildCastNode(); - castStringScalar = newCastBuilder().asStringVector().findFirst(RRuntime.STRING_NA).buildCastNode(); - } + @Child private CastNode castIntScalar = newCastBuilder().asIntegerVector().findFirst(RRuntime.INT_NA).buildCastNode(); + @Child private CastNode castStringScalar = newCastBuilder().asStringVector().findFirst(RRuntime.STRING_NA).buildCastNode(); private final BranchProfile noGenFunFound = BranchProfile.create(); private final ConditionProfile sameNamesProfile = ConditionProfile.createBinaryProfile(); @@ -82,11 +78,18 @@ public abstract class StandardGeneric extends RBuiltinNode { casts.arg("f").defaultError(RError.Message.GENERIC, "argument to 'standardGeneric' must be a non-empty character string").mustBe( stringValue()).asStringVector().findFirst().mustBe(lengthGt(0)); Function<Object, Object> argClass = ClassHierarchyScalarNode::get; - casts.arg("fdef").defaultError(RError.SHOW_CALLER, RError.Message.EXPECTED_GENERIC, argClass).allowMissing().asAttributable(true, true, true).mustBe(instanceOf(RFunction.class)); + casts.arg("fdef").defaultError(RError.Message.EXPECTED_GENERIC, argClass).allowMissing().asAttributable(true, true, true).mustBe(instanceOf(RFunction.class)); } private Object stdGenericInternal(VirtualFrame frame, String fname, RFunction fdef) { - MaterializedFrame fnFrame = fdef.getEnclosingFrame(); + RFunction def = fdef; + if (def.isBuiltin()) { + def = RContext.getInstance().getPrimitiveMethodsInfo().getPrimGeneric(def.getRBuiltin().getPrimMethodIndex()); + if (def == null) { + return RRuntime.DEFERRED_DEFAULT_MARKER; + } + } + MaterializedFrame fnFrame = def.getEnclosingFrame(); REnvironment mtable = (REnvironment) readMTableFirst.execute(frame, fnFrame); if (mtable == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -94,19 +97,19 @@ public abstract class StandardGeneric extends RBuiltinNode { // and this slow path should not be executed again REnvironment methodsEnv = REnvironment.getRegisteredNamespace("methods"); RFunction currentFunction = ReadVariableNode.lookupFunction(".getMethodsTable", methodsEnv.getFrame(), true, true); - mtable = (REnvironment) RContext.getEngine().evalFunction(currentFunction, frame.materialize(), RCaller.create(frame, getOriginalCall()), null, fdef); + mtable = (REnvironment) RContext.getEngine().evalFunction(currentFunction, frame.materialize(), RCaller.create(frame, getOriginalCall()), null, def); } RList sigArgs = (RList) readSigARgs.execute(null, fnFrame); - int sigLength = (int) castIntScalar.execute(readSigLength.execute(null, fnFrame)); + int sigLength = (int) castIntScalar.doCast(readSigLength.execute(null, fnFrame)); if (sigLength > sigArgs.getLength()) { - throw RError.error(this, RError.Message.GENERIC, "'.SigArgs' is shorter than '.SigLength' says it should be"); + throw error(RError.Message.GENERIC, "'.SigArgs' is shorter than '.SigLength' says it should be"); } if (collectArgumentsNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); collectArgumentsNode = insert(CollectGenericArgumentsNodeGen.create(sigArgs.getDataWithoutCopying(), sigLength)); } RStringVector classes = collectArgumentsNode.execute(frame, sigArgs, sigLength); - Object ret = dispatchGeneric.executeObject(frame, mtable, classes, fdef, fname); + Object ret = dispatchGeneric.executeObject(frame, mtable, classes, def, fname); return ret; } @@ -131,7 +134,7 @@ public abstract class StandardGeneric extends RBuiltinNode { noGenFunFound.enter(); return null; } - String gen = (String) castStringScalar.execute(genObj); + String gen = (String) castStringScalar.doCast(genObj); if (sameNamesProfile.profile(gen == fname)) { return stdGenericInternal(frame, fname, fn); } else { @@ -173,6 +176,6 @@ public abstract class StandardGeneric extends RBuiltinNode { return fnObj; } } - throw RError.error(this, RError.Message.STD_GENERIC_WRONG_CALL, fname); + throw error(RError.Message.STD_GENERIC_WRONG_CALL, fname); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StartsEndsWithFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StartsEndsWithFunctions.java index 32242b09d479d77c98832aece324b779a1445c39..a92d62da66437edbd8a72a9e0a1770ab8cd8a179 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StartsEndsWithFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StartsEndsWithFunctions.java @@ -38,12 +38,12 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; public class StartsEndsWithFunctions { - private abstract static class Adapter extends RBuiltinNode { + private abstract static class Adapter extends RBuiltinNode.Arg2 { private final NACheck naCheck = NACheck.create(); private final ConditionProfile singlePrefixProfile = ConditionProfile.createBinaryProfile(); private static void argCast(Casts casts, String name) { - casts.arg(name).mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.NON_CHARACTER_OBJECTS).asStringVector(); + casts.arg(name).mustBe(stringValue(), RError.Message.NON_CHARACTER_OBJECTS).asStringVector(); } protected static Casts createCasts(Class<? extends Adapter> extCls) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Stop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Stop.java index efb1ada9f48b86cc105facbdc6b621367404c7c2..6012893ec50ceb2bf6035604ab840452b369dd84 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Stop.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Stop.java @@ -36,7 +36,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RNull; @RBuiltin(name = "stop", kind = INTERNAL, parameterNames = {"call", "message"}, behavior = COMPLEX) -public abstract class Stop extends RBuiltinNode { +public abstract class Stop extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(Stop.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java index 6710bae7b4cab953d06866004c5da948a3a14f21..46455a6a6021b4da55619c8292f9e0f0ec5d9fc8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java @@ -32,19 +32,20 @@ import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RNull; 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.ops.na.NACheck; @RBuiltin(name = "strrep", kind = INTERNAL, parameterNames = {"x", "times"}, behavior = PURE) -public abstract class Strrep extends RBuiltinNode { +public abstract class Strrep extends RBuiltinNode.Arg2 { private final NACheck naCheck = NACheck.create(); static { Casts casts = new Casts(Strrep.class); - casts.arg("x").asStringVector(); - casts.arg("times").asIntegerVector(); + casts.arg("x").mustNotBeMissing().asStringVector(); + casts.arg("times").mustNotBeMissing().asIntegerVector(); } @Specialization @@ -67,7 +68,7 @@ public abstract class Strrep extends RBuiltinNode { data[i] = RRuntime.STRING_NA; } else { if (times < 0) { - throw RError.error(this, RError.Message.INVALID_VALUE, "times"); + throw error(RError.Message.INVALID_VALUE, "times"); } if (times == 1) { data[i] = x; @@ -89,6 +90,18 @@ public abstract class Strrep extends RBuiltinNode { return result; } + @Specialization + protected Object strrep(RNull xVec, RAbstractIntVector timesVec) { + return RDataFactory.createEmptyStringVector(); // GnuR fails with segfault; return value + // adheres to non-internal strrep() result + } + + @Specialization + protected Object strrep(RAbstractStringVector xVec, RNull timesVec) { + return RDataFactory.createEmptyStringVector(); // GnuR - infinite loop; return value adheres + // to non-internal strrep() result + } + @TruffleBoundary private static void copyNames(RAbstractStringVector xVec, RStringVector result) { result.copyNamesFrom(xVec); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtoi.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtoi.java index 86e2c0b11b9505253434ebbe8d8cf6805ccf9219..57d4d6171b68c21d7dae1079de4df35e69db4542 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtoi.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtoi.java @@ -43,7 +43,7 @@ import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "strtoi", kind = INTERNAL, parameterNames = {"x", "base"}, behavior = PURE) -public abstract class Strtoi extends RBuiltinNode { +public abstract class Strtoi extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(Strtoi.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java index 9fb1980325dc7f5fa7887cd8d9b6088efd8e4472..473d041dbbc889dac22cd2ee29b27bf7ab72a083 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java @@ -12,6 +12,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -34,12 +35,12 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "strtrim", kind = INTERNAL, parameterNames = {"x", "width"}, behavior = PURE) -public abstract class Strtrim extends RBuiltinNode { +public abstract class Strtrim extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(Strtrim.class); casts.arg("x").defaultError(Message.REQUIRES_CHAR_VECTOR, "strtrim()").mustBe(stringValue()).asStringVector(true, true, true); - casts.arg("width").asIntegerVector(); + casts.arg("width").mustNotBeMissing().mustBe(nullValue().not()).asIntegerVector(); } @Specialization @@ -50,13 +51,13 @@ public abstract class Strtrim extends RBuiltinNode { int nw = width.getLength(); if (nw == 0 || nw < len && (len % nw != 0)) { CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "width"); + throw error(RError.Message.INVALID_ARGUMENT, "width"); } for (int i = 0; i < nw; i++) { assert RRuntime.INT_NA < 0; // check for NA folded into < 0 if (width.getDataAt(i) < 0) { CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "width"); + throw error(RError.Message.INVALID_ARGUMENT, "width"); } } BiFunction<String, Integer, String> function = (element, i) -> { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java index 8f75d3805283f2630e15b5072874c9e3b4d7c5fe..5f20186adf19dec50fb43938b0e92e0081f7c3f9 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java @@ -48,13 +48,13 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.env.REnvironment; @RBuiltin(name = "substitute", kind = PRIMITIVE, parameterNames = {"expr", "env"}, nonEvalArgs = 0, behavior = COMPLEX) -public abstract class Substitute extends RBuiltinNode { +public abstract class Substitute extends RBuiltinNode.Arg2 { @Child private Quote quote; static { Casts casts = new Casts(Substitute.class); - casts.arg(1).allowNullAndMissing().defaultError(INVALID_ENVIRONMENT_SPECIFIED).mustBe(instanceOf(RAbstractListVector.class).or(instanceOf(REnvironment.class))); + casts.arg(1).defaultError(INVALID_ENVIRONMENT_SPECIFIED).allowNullAndMissing().mustBe(instanceOf(RAbstractListVector.class).or(instanceOf(REnvironment.class))); } @Specialization @@ -73,7 +73,7 @@ public abstract class Substitute extends RBuiltinNode { } @Specialization(guards = {"list.getNames() == null || list.getNames().getLength() == 0"}) - protected Object doSubstitute(RPromise expr, RList list) { + protected Object doSubstitute(RPromise expr, @SuppressWarnings("unused") RList list) { return doSubstituteWithEnv(expr, SubstituteDirect.createNewEnvironment()); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.java index b55b50f9431765f56c66c64914e0a0e07c12b3ea..f3c3760c13d7ecc8a04fb997746daf8b64f216e8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.java @@ -42,7 +42,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "substr", kind = INTERNAL, parameterNames = {"x", "start", "stop"}, behavior = PURE) -public abstract class Substr extends RBuiltinNode { +public abstract class Substr extends RBuiltinNode.Arg3 { private final NACheck na = NACheck.create(); private final BranchProfile everSeenIllegalRange = BranchProfile.create(); private final ConditionProfile naIndexesProfile = ConditionProfile.createBinaryProfile(); @@ -140,7 +140,7 @@ public abstract class Substr extends RBuiltinNode { protected boolean wrongParams(RAbstractIntVector start, RAbstractIntVector stop) { if (start.getLength() == 0 || stop.getLength() == 0) { - throw RError.error(this, RError.Message.INVALID_ARGUMENTS_NO_QUOTE, "substring"); + throw error(RError.Message.INVALID_ARGUMENTS_NO_QUOTE, "substring"); } return false; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java index b8a914baf11c67dbfe8b66755ee5d500272c3c6f..aa347076a2f0e0fcf512add9cbaac212438da4a8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java @@ -42,7 +42,7 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RDoubleVector; -import com.oracle.truffle.r.runtime.ffi.RFFIFactory; +import com.oracle.truffle.r.runtime.ffi.MiscRFFI; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; import com.oracle.truffle.r.runtime.ops.na.NACheck; @@ -50,7 +50,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; * Sum has combine semantics (TBD: exactly?) and uses a reduce operation on the resulting array. */ @RBuiltin(name = "sum", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE) -public abstract class Sum extends RBuiltinNode { +public abstract class Sum extends RBuiltinNode.Arg2 { protected static final boolean FULL_PRECISION = FastROptions.FullPrecisionSum.getBooleanValue(); @@ -60,7 +60,7 @@ public abstract class Sum extends RBuiltinNode { static { Casts casts = new Casts(Sum.class); - casts.arg("na.rm").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean()); + casts.arg("na.rm").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); } @Override @@ -78,12 +78,13 @@ public abstract class Sum extends RBuiltinNode { @Cached("create()") VectorLengthProfile lengthProfile, @Cached("createCountingProfile()") LoopConditionProfile loopProfile, @Cached("create()") NACheck na, - @Cached("createBinaryProfile()") ConditionProfile needsExactSumProfile) { + @Cached("createBinaryProfile()") ConditionProfile needsExactSumProfile, + @Cached("create()") MiscRFFI.ExactSumNode exactSumNode) { RDoubleVector vector = (RDoubleVector) args.getArgument(0); int length = lengthProfile.profile(vector.getLength()); if (needsExactSumProfile.profile(length >= 3)) { - return RFFIFactory.getRFFI().getMiscRFFI().exactSum(vector.getDataWithoutCopying(), !vector.isComplete(), cachedNaRm); + return exactSumNode.execute(vector.getDataWithoutCopying(), !vector.isComplete(), cachedNaRm); } else { na.enable(vector); loopProfile.profileCounted(length); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java index d1af871ffb367e3cde17326d76c03714d445bfd7..e266bceac2765ababb0878140efd737a41bff344 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java @@ -11,11 +11,16 @@ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicIntegerValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.findFirst; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.runtime.RVisibility.CUSTOM; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.BranchProfile; @@ -24,17 +29,17 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode; import com.oracle.truffle.r.nodes.function.RMissingHelper; import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; -import com.oracle.truffle.r.nodes.unary.CastIntegerNode; -import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RDeparse; 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.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; -import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RExpression; +import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPromise; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; /** * The {@code switch} builtin. When called directly, the "..." arguments are not evaluated before @@ -45,9 +50,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; * */ @RBuiltin(name = "switch", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"EXPR", "..."}, nonEvalArgs = 1, behavior = COMPLEX) -public abstract class Switch extends RBuiltinNode { +public abstract class Switch extends RBuiltinNode.Arg2 { - @Child private CastIntegerNode castIntNode; @Child private PromiseCheckHelperNode promiseHelper = new PromiseCheckHelperNode(); @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); @@ -60,24 +64,46 @@ public abstract class Switch extends RBuiltinNode { private final ConditionProfile noAlternativesProfile = ConditionProfile.createBinaryProfile(); static { - Casts.noCasts(Switch.class); + // @formatter:off + Casts casts = new Casts(Switch.class); + // first argument must be list or expression or vector of size 1, if it is not String, cast it to integer + casts.arg("EXPR").defaultError(RError.Message.EXPR_NOT_LENGTH_ONE). + mustNotBeMissing(RError.Message.EXPR_MISSING). + returnIf(atomicIntegerValue().or(instanceOf(String.class)).or(instanceOf(RExpression.class))). + mustBe(abstractVectorValue()).boxPrimitive().mustBe(size(1)). + returnIf(stringValue(), findFirst().stringElement()). + returnIf(instanceOf(RList.class)). + asIntegerVector().findFirst(); + // @formatter:on } + // Note: GnuR returns NULL for lists/expressions, even if they contain a signle number, which + // could be interpreted as integer + @Specialization - protected Object doSwitch(VirtualFrame frame, RAbstractStringVector x, RArgsValuesAndNames optionalArgs) { - if (x.getLength() != 1) { - throw RError.error(this, RError.Message.EXPR_NOT_LENGTH_ONE); + protected Object doSwitchList(VirtualFrame frame, RList list, @SuppressWarnings("unused") RArgsValuesAndNames optionalArgs) { + return prepareResult(frame, null); + } + + @Specialization + protected Object doSwitchExpr(VirtualFrame frame, RExpression expr, @SuppressWarnings("unused") RArgsValuesAndNames optionalArgs) { + if (expr.getLength() != 1) { + throw error(Message.EXPR_NOT_LENGTH_ONE); } + return prepareResult(frame, null); + } + + @Specialization + protected Object doSwitch(VirtualFrame frame, String x, RArgsValuesAndNames optionalArgs) { return prepareResult(frame, doSwitchString(frame, x, optionalArgs)); } - private Object doSwitchString(VirtualFrame frame, RAbstractStringVector x, RArgsValuesAndNames optionalArgs) { + private Object doSwitchString(VirtualFrame frame, String xStr, RArgsValuesAndNames optionalArgs) { if (noAlternativesProfile.profile(optionalArgs.getLength() == 0)) { - RError.warning(this, RError.Message.NO_ALTERNATIVES_IN_SWITCH); + warning(RError.Message.NO_ALTERNATIVES_IN_SWITCH); return null; } Object[] optionalArgValues = optionalArgs.getArguments(); - final String xStr = x.getDataAt(0); ArgumentsSignature signature = optionalArgs.getSignature(); for (int i = 0; i < signature.getLength(); i++) { final String suppliedArgName = signature.getName(i); @@ -116,7 +142,7 @@ public abstract class Switch extends RBuiltinNode { suppliedArgNameIsNull.enter(); Object optionalArg = optionalArgValues[i]; if (currentDefaultProfile.profile(currentDefault != null)) { - throw RError.error(this, RError.Message.DUPLICATE_SWITCH_DEFAULT, deparseDefault(currentDefault), deparseDefault(optionalArg)); + throw error(RError.Message.DUPLICATE_SWITCH_DEFAULT, deparseDefault(currentDefault), deparseDefault(optionalArg)); } else { currentDefault = optionalArg; } @@ -141,33 +167,17 @@ public abstract class Switch extends RBuiltinNode { @Specialization protected Object doSwitch(VirtualFrame frame, int x, RArgsValuesAndNames optionalArgs) { - return prepareResult(frame, doSwitchInt(frame, x, optionalArgs)); - } - - @Specialization - protected Object doSwitch(VirtualFrame frame, Object x, RArgsValuesAndNames optionalArgs) { - if (castIntNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castIntNode = insert(CastIntegerNodeGen.create(false, false, false)); - } - Object objIndex = castIntNode.execute(x); - if (!(objIndex instanceof Integer)) { + if (RRuntime.isNA(x)) { + // cast pipeline gives us NA for non-integer value notIntType.enter(); - return null; + return prepareResult(frame, null); } - return prepareResult(frame, doSwitchInt(frame, (int) objIndex, optionalArgs)); - } - - @SuppressWarnings("unused") - @Specialization - protected Object doSwitch(RMissing x, RMissing optionalArgs) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.EXPR_MISSING); + return prepareResult(frame, doSwitchInt(frame, x, optionalArgs)); } private Object doSwitchInt(VirtualFrame frame, int index, RArgsValuesAndNames optionalArgs) { if (noAlternativesProfile.profile(optionalArgs.getLength() == 0)) { - RError.warning(this, RError.Message.NO_ALTERNATIVES_IN_SWITCH); + warning(RError.Message.NO_ALTERNATIVES_IN_SWITCH); return null; } Object[] optionalArgValues = optionalArgs.getArguments(); @@ -176,7 +186,7 @@ public abstract class Switch extends RBuiltinNode { if (value != null) { return value; } - throw RError.error(this, RError.Message.NO_ALTERNATIVE_IN_SWITCH); + throw error(RError.Message.NO_ALTERNATIVE_IN_SWITCH); } return null; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SysFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SysFunctions.java index cc35e6facb3475aecbfbf0572f472696085adbb7..ea2f8107dc40567fefc4e7bff43368127a0524d7 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SysFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SysFunctions.java @@ -74,7 +74,7 @@ import com.oracle.truffle.r.runtime.ffi.BaseRFFI.UtsName; public class SysFunctions { @RBuiltin(name = "Sys.getpid", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) - public abstract static class SysGetpid extends RBuiltinNode { + public abstract static class SysGetpid extends RBuiltinNode.Arg0 { @Child private BaseRFFI.GetpidNode getpidNode = BaseRFFI.GetpidNode.create(); @Specialization @@ -86,7 +86,7 @@ public class SysFunctions { } @RBuiltin(name = "Sys.getenv", kind = INTERNAL, parameterNames = {"x", "unset"}, behavior = READS_STATE) - public abstract static class SysGetenv extends RBuiltinNode { + public abstract static class SysGetenv extends RBuiltinNode.Arg2 { private final ConditionProfile zeroLengthProfile = ConditionProfile.createBinaryProfile(); static { @@ -135,33 +135,31 @@ public class SysFunctions { * code depends critically in the current implementation which sets/unsets this environment * variable around a call to loadNamespace/attachNamespace. */ - protected abstract static class LoadNamespaceAdapter extends RBuiltinNode { - private static final String NS_LOAD = "_R_NS_LOAD_"; - private static final String LOADNAMESPACE = "loadNamespace"; + private static final String NS_LOAD = "_R_NS_LOAD_"; + private static final String LOADNAMESPACE = "loadNamespace"; - protected void checkNSLoad(VirtualFrame frame, RAbstractStringVector names, RAbstractStringVector values, boolean setting) { - if (names.getLength() == 1 && NS_LOAD.equals(names.getDataAt(0))) { - doCheckNSLoad(frame.materialize(), values, setting); - } + protected static void checkNSLoad(VirtualFrame frame, RAbstractStringVector names, RAbstractStringVector values, boolean setting) { + if (names.getLength() == 1 && NS_LOAD.equals(names.getDataAt(0))) { + doCheckNSLoad(frame.materialize(), values, setting); } + } - @TruffleBoundary - private static void doCheckNSLoad(MaterializedFrame frame, RAbstractStringVector values, boolean setting) { - Frame caller = Utils.getCallerFrame(frame, FrameAccess.READ_ONLY); - RFunction func = RArguments.getFunction(caller); - if (func.toString().equals(LOADNAMESPACE)) { - if (setting) { - RContext.getInstance().setNamespaceName(values.getDataAt(0)); - } else { - // Now we can run the overrides - RBuiltinPackages.loadDefaultPackageOverrides(RContext.getInstance().getNamespaceName()); - } + @TruffleBoundary + private static void doCheckNSLoad(MaterializedFrame frame, RAbstractStringVector values, boolean setting) { + Frame caller = Utils.getCallerFrame(frame, FrameAccess.READ_ONLY); + RFunction func = RArguments.getFunction(caller); + if (func.toString().equals(LOADNAMESPACE)) { + if (setting) { + RContext.getInstance().setNamespaceName(values.getDataAt(0)); + } else { + // Now we can run the overrides + RBuiltinPackages.loadDefaultPackageOverrides(RContext.getInstance().getNamespaceName()); } } } @RBuiltin(name = "Sys.setenv", visibility = OFF, kind = INTERNAL, parameterNames = {"nm", "values"}, behavior = MODIFIES_STATE) - public abstract static class SysSetEnv extends LoadNamespaceAdapter { + public abstract static class SysSetEnv extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(SysSetEnv.class); @@ -172,7 +170,7 @@ public class SysFunctions { @Specialization protected RLogicalVector doSysSetEnv(VirtualFrame frame, RAbstractStringVector names, RAbstractStringVector values) { if (names.getLength() != values.getLength()) { - throw RError.error(this, RError.Message.ARGUMENT_WRONG_LENGTH); + throw error(RError.Message.ARGUMENT_WRONG_LENGTH); } checkNSLoad(frame, names, values, true); return doSysSetEnv(names, values); @@ -191,7 +189,7 @@ public class SysFunctions { } @RBuiltin(name = "Sys.unsetenv", visibility = OFF, kind = INTERNAL, parameterNames = {"x"}, behavior = READS_STATE) - public abstract static class SysUnSetEnv extends LoadNamespaceAdapter { + public abstract static class SysUnSetEnv extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(SysUnSetEnv.class); @@ -217,7 +215,7 @@ public class SysFunctions { } @RBuiltin(name = "Sys.sleep", visibility = OFF, kind = INTERNAL, parameterNames = {"time"}, behavior = COMPLEX) - public abstract static class SysSleep extends RBuiltinNode { + public abstract static class SysSleep extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(SysSleep.class); @@ -248,7 +246,7 @@ public class SysFunctions { * TODO: Handle ~ expansion which is not handled by POSIX. */ @RBuiltin(name = "Sys.readlink", kind = INTERNAL, parameterNames = {"paths"}, behavior = IO) - public abstract static class SysReadlink extends RBuiltinNode { + public abstract static class SysReadlink extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(SysReadlink.class); @@ -291,13 +289,13 @@ public class SysFunctions { } @RBuiltin(name = "Sys.chmod", visibility = OFF, kind = INTERNAL, parameterNames = {"paths", "octmode", "use_umask"}, behavior = IO) - public abstract static class SysChmod extends RBuiltinNode { + public abstract static class SysChmod extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(SysChmod.class); casts.arg("paths").mustBe(stringValue()); casts.arg("octmode").asIntegerVector().mustBe(notEmpty(), RError.Message.MODE_LENGTH_ONE); - casts.arg("use_umask").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("use_umask").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } @Specialization @@ -319,7 +317,7 @@ public class SysFunctions { // TODO implement @RBuiltin(name = "Sys.umask", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"octmode"}, behavior = COMPLEX) - public abstract static class SysUmask extends RBuiltinNode { + public abstract static class SysUmask extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(SysUmask.class); @@ -335,7 +333,7 @@ public class SysFunctions { } @RBuiltin(name = "Sys.time", kind = INTERNAL, parameterNames = {}, behavior = IO) - public abstract static class SysTime extends RBuiltinNode { + public abstract static class SysTime extends RBuiltinNode.Arg0 { @Specialization @TruffleBoundary protected double sysTime() { @@ -344,7 +342,7 @@ public class SysFunctions { } @RBuiltin(name = "Sys.info", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) - public abstract static class SysInfo extends RBuiltinNode { + public abstract static class SysInfo extends RBuiltinNode.Arg0 { private static final String[] NAMES = new String[]{"sysname", "release", "version", "nodename", "machine", "login", "user", "effective_user"}; private static final RStringVector NAMES_ATTR = RDataFactory.createStringVector(NAMES, RDataFactory.COMPLETE_VECTOR); @@ -370,12 +368,12 @@ public class SysFunctions { } @RBuiltin(name = "Sys.glob", kind = INTERNAL, parameterNames = {"paths", "dirmask"}, behavior = IO) - public abstract static class SysGlob extends RBuiltinNode { + public abstract static class SysGlob extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(SysGlob.class); casts.arg("paths").mustBe(stringValue()).asStringVector(); - casts.arg("dirmask").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("dirmask").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } @Specialization @@ -399,12 +397,12 @@ public class SysFunctions { } @RBuiltin(name = "setFileTime", kind = INTERNAL, parameterNames = {"path", "time"}, visibility = OFF, behavior = IO) - public abstract static class SysSetFileTime extends RBuiltinNode { + public abstract static class SysSetFileTime extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(SysSetFileTime.class); casts.arg("path").mustBe(stringValue()).asStringVector().findFirst(); - casts.arg("time").asIntegerVector().findFirst().notNA(); + casts.arg("time").asIntegerVector().findFirst().mustNotBeNA(); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java index bbe48d983e50afa4cf6352fcb2e9c01ac3342efd..be218cc4bdaa1b350bc24a5531fdcdebde22e102 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java @@ -26,14 +26,14 @@ import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @RBuiltin(name = "tabulate", kind = INTERNAL, parameterNames = {"bin", "nbins"}, behavior = PURE) -public abstract class Tabulate extends RBuiltinNode { +public abstract class Tabulate extends RBuiltinNode.Arg2 { private final LoopConditionProfile loopProfile = LoopConditionProfile.createCountingProfile(); static { Casts casts = new Casts(Tabulate.class); - casts.arg("bin").defaultError(RError.NO_CALLER, RError.Message.INVALID_INPUT).mustBe(integerValue()).asIntegerVector(); - casts.arg("nbins").defaultError(RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "nbin").asIntegerVector().findFirst().mustBe(gte(0)); + casts.arg("bin").defaultError(RError.Message.INVALID_INPUT).mustBe(integerValue()).asIntegerVector(); + casts.arg("nbins").defaultError(RError.Message.INVALID_ARGUMENT, "nbin").asIntegerVector().findFirst().mustBe(gte(0)); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempDir.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempDir.java index 022c03adde708e6e668cacd60f45ead87c70599b..d54dbc9845bcac5b867bf9f1294bfb02595c2c7a 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempDir.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempDir.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 @@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; @RBuiltin(name = "tempdir", kind = INTERNAL, parameterNames = {}, behavior = RBehavior.READS_STATE) -public abstract class TempDir extends RBuiltinNode { +public abstract class TempDir extends RBuiltinNode.Arg0 { @Specialization protected Object tempdir() { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempFile.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempFile.java index 2bb1e17c5c3b177e8234a19de9fb86254b74301a..20632a8ef93cd04825ac665510efc6c5b07257bb 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempFile.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempFile.java @@ -39,13 +39,13 @@ import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "tempfile", kind = INTERNAL, parameterNames = {"pattern", "tempdir", "fileext"}, behavior = COMPLEX) -public abstract class TempFile extends RBuiltinNode { +public abstract class TempFile extends RBuiltinNode.Arg3 { static { Casts casts = new Casts(TempFile.class); - casts.arg("pattern").asVector().mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.INVALID_FILENAME_PATTERN).mustBe(notEmpty(), RError.SHOW_CALLER, RError.Message.NO, "pattern"); - casts.arg("tempdir").asVector().mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.INVALID_VALUE, "tempdir").findFirst(RError.SHOW_CALLER, RError.Message.NO, "tempdir"); - casts.arg("fileext").asVector().mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.INVALID_FILE_EXT).mustBe(notEmpty(), RError.SHOW_CALLER, RError.Message.NO, "fileext"); + casts.arg("pattern").asVector().mustBe(stringValue(), RError.Message.INVALID_FILENAME_PATTERN).mustBe(notEmpty(), RError.Message.NO, "pattern"); + casts.arg("tempdir").asVector().mustBe(stringValue(), RError.Message.INVALID_VALUE, "tempdir").findFirst(RError.Message.NO, "tempdir"); + casts.arg("fileext").asVector().mustBe(stringValue(), RError.Message.INVALID_FILE_EXT).mustBe(notEmpty(), RError.Message.NO, "fileext"); } @TruffleBoundary diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ToLowerOrUpper.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ToLowerOrUpper.java index 92d3eb1c98b110834b76f3ca6de0c7dd5ab6df48..7078e5bb37dc2d44cc13d2f0b43f9c34110d81e9 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ToLowerOrUpper.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ToLowerOrUpper.java @@ -90,7 +90,7 @@ public abstract class ToLowerOrUpper { } @RBuiltin(name = "tolower", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) - public abstract static class ToLower extends RBuiltinNode { + public abstract static class ToLower extends RBuiltinNode.Arg1 { @Child private StringMapNode mapNode = StringMapNode.create(); @@ -116,7 +116,7 @@ public abstract class ToLowerOrUpper { } @RBuiltin(name = "toupper", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) - public abstract static class ToUpper extends RBuiltinNode { + public abstract static class ToUpper extends RBuiltinNode.Arg1 { @Child private StringMapNode mapNode = StringMapNode.create(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java index 5521a01b4d0244172289017dce886884108a7391..653e415b77a237fbe5ff6ce295e658208f95aa44 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java @@ -27,7 +27,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.findFirst; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; -import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; import static com.oracle.truffle.r.runtime.RVisibility.CUSTOM; import static com.oracle.truffle.r.runtime.RVisibility.OFF; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; @@ -44,6 +43,7 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.GetFunctionsFactory.GetNodeGen; import com.oracle.truffle.r.nodes.builtin.helpers.TraceHandling; @@ -66,15 +66,15 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; public class TraceFunctions { - private abstract static class PrimTraceAdapter extends RBuiltinNode { - @Child private GetFunctions.Get getNode; + protected static Casts createCasts(Class<? extends RBuiltinNode> extCls) { + Casts casts = new Casts(extCls); + casts.arg("what").mustBe(instanceOf(RFunction.class).or(stringValue()), Message.ARG_MUST_BE_FUNCTION).mapIf(stringValue(), + chain(asStringVector()).with(findFirst().stringElement()).end()); + return casts; + } - protected static Casts createCasts(Class<? extends PrimTraceAdapter> extCls) { - Casts casts = new Casts(extCls); - casts.arg("what").mustBe(instanceOf(RFunction.class).or(stringValue()), SHOW_CALLER, Message.ARG_MUST_BE_FUNCTION).mapIf(stringValue(), - chain(asStringVector()).with(findFirst().stringElement()).end()); - return casts; - } + private abstract static class PrimTraceAdapter extends RBuiltinNode.Arg1 { + @Child private GetFunctions.Get getNode; protected Object getFunction(VirtualFrame frame, String funcName) { if (getNode == null) { @@ -92,6 +92,8 @@ public class TraceFunctions { createCasts(PrimTrace.class); } + public abstract Object execute(VirtualFrame frame, RFunction func); + @Specialization protected RNull primTrace(VirtualFrame frame, RAbstractStringVector funcName) { return primTrace((RFunction) getFunction(frame, funcName.getDataAt(0))); @@ -103,10 +105,11 @@ public class TraceFunctions { if (!func.isBuiltin()) { TraceHandling.enableTrace(func); } else { - throw RError.error(this, RError.Message.GENERIC, "builtin functions cannot be traced"); + throw error(RError.Message.GENERIC, "builtin functions cannot be traced"); } return RNull.instance; } + } @RBuiltin(name = ".primUntrace", visibility = OFF, kind = PRIMITIVE, parameterNames = "what", behavior = COMPLEX) @@ -116,6 +119,8 @@ public class TraceFunctions { createCasts(PrimUnTrace.class); } + public abstract Object execute(VirtualFrame frame, RFunction func); + @Specialization protected RNull primUnTrace(VirtualFrame frame, RAbstractStringVector funcName) { return primUnTrace((RFunction) getFunction(frame, funcName.getDataAt(0))); @@ -129,10 +134,11 @@ public class TraceFunctions { } return RNull.instance; } + } @RBuiltin(name = "traceOnOff", kind = INTERNAL, parameterNames = "state", behavior = COMPLEX) - public abstract static class TraceOnOff extends RBuiltinNode { + public abstract static class TraceOnOff extends RBuiltinNode.Arg1 { static { Casts.noCasts(TraceOnOff.class); @@ -158,68 +164,66 @@ public class TraceFunctions { } } - public abstract static class TracememBase extends RBuiltinNode { - static { - MemoryCopyTracer.addListener(new TracememBase.TracememListener()); - } + static { + MemoryCopyTracer.addListener(new TracememListener()); + } - @TruffleBoundary - protected static HashSet<Object> getTracedObjects() { - return RContext.getInstance().getInstrumentationState().getTracemem().getTracedObjects(); - } + @TruffleBoundary + protected static HashSet<Object> getTracedObjects() { + return RContext.getInstance().getInstrumentationState().getTracemem().getTracedObjects(); + } - @TruffleBoundary - protected static String formatHashCode(Object x) { - return String.format("<0x%x>", x.hashCode()); - } + @TruffleBoundary + protected static String formatHashCode(Object x) { + return String.format("<0x%x>", x.hashCode()); + } - @TruffleBoundary - protected static void startTracing(Object x) { - /* - * There is no explicit command to enable tracing, it is implicit in the call to - * tracemem. However, it can be disabled by tracingState(F), so we can't unilaterally - * turn on tracing here. - */ - getTracedObjects().add(x); - boolean tracingState = RContext.getInstance().stateInstrumentation.getTracingState(); - if (tracingState) { - MemoryCopyTracer.setTracingState(true); - } + @TruffleBoundary + protected static void startTracing(Object x) { + /* + * There is no explicit command to enable tracing, it is implicit in the call to tracemem. + * However, it can be disabled by tracingState(F), so we can't unilaterally turn on tracing + * here. + */ + getTracedObjects().add(x); + boolean tracingState = RContext.getInstance().stateInstrumentation.getTracingState(); + if (tracingState) { + MemoryCopyTracer.setTracingState(true); } + } - @TruffleBoundary - protected static void printToStdout(String msg) { - try { - StdConnections.getStdout().writeString(msg, true); - } catch (IOException ex) { - throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, ex.getMessage()); - } + @TruffleBoundary + protected static void printToStdout(String msg) { + try { + StdConnections.getStdout().writeString(msg, true); + } catch (IOException ex) { + throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, ex.getMessage()); } + } - @TruffleBoundary - protected static String getStackTrace() { - final StringBuffer result = new StringBuffer(); - Truffle.getRuntime().iterateFrames(frame -> { - Frame unwrapped = RArguments.unwrap(frame.getFrame(FrameAccess.READ_ONLY)); - if (RArguments.isRFrame(unwrapped)) { - RCaller call = RArguments.getCall(unwrapped); - if (call != null && call.isValidCaller()) { - result.append(RContext.getRRuntimeASTAccess().getCallerSource(call)); - result.append(' '); - } + @TruffleBoundary + protected static String getStackTrace() { + final StringBuffer result = new StringBuffer(); + Truffle.getRuntime().iterateFrames(frame -> { + Frame unwrapped = RArguments.unwrap(frame.getFrame(FrameAccess.READ_ONLY)); + if (RArguments.isRFrame(unwrapped)) { + RCaller call = RArguments.getCall(unwrapped); + if (call != null && call.isValidCaller()) { + result.append(RContext.getRRuntimeASTAccess().getCallerSource(call)); + result.append(' '); } - return null; - }); - return result.toString(); - } + } + return null; + }); + return result.toString(); + } - private static final class TracememListener implements MemoryCopyTracer.Listener { - @TruffleBoundary - @Override - public void reportCopying(RAbstractVector src, RAbstractVector dest) { - if (getTracedObjects().contains(src)) { - printToStdout(String.format("tracemem[0x%x -> 0x%x]: %s", src.hashCode(), dest.hashCode(), getStackTrace())); - } + private static final class TracememListener implements MemoryCopyTracer.Listener { + @TruffleBoundary + @Override + public void reportCopying(RAbstractVector src, RAbstractVector dest) { + if (getTracedObjects().contains(src)) { + printToStdout(String.format("tracemem[0x%x -> 0x%x]: %s", src.hashCode(), dest.hashCode(), getStackTrace())); } } } @@ -230,7 +234,7 @@ public class TraceFunctions { * temporary vector wrappers cannot be traced however. */ @RBuiltin(name = "tracemem", kind = PRIMITIVE, parameterNames = "x", behavior = COMPLEX) - public abstract static class Tracemem extends TracememBase { + public abstract static class Tracemem extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(Tracemem.class); @@ -250,13 +254,13 @@ public class TraceFunctions { * unclear meaning. */ @RBuiltin(name = "retracemem", kind = PRIMITIVE, visibility = CUSTOM, parameterNames = {"x", "previous"}, behavior = COMPLEX) - public abstract static class Retracemem extends TracememBase { + public abstract static class Retracemem extends RBuiltinNode.Arg2 { @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); static { Casts casts = new Casts(Retracemem.class); - casts.arg("previous").defaultError(Message.INVALID_ARGUMENT, "previous").allowNullAndMissing().mustBe(stringValue()); + casts.arg("previous").defaultError(Message.INVALID_ARGUMENT, "previous").allowNullAndMissing().mustBe(stringValue()).asStringVector().findFirst(); } @Specialization @@ -292,7 +296,7 @@ public class TraceFunctions { } @RBuiltin(name = "untracemem", kind = PRIMITIVE, visibility = OFF, parameterNames = "x", behavior = COMPLEX) - public abstract static class Untracemem extends TracememBase { + public abstract static class Untracemem extends RBuiltinNode.Arg1 { static { Casts.noCasts(Untracemem.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Traceback.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Traceback.java index 4c75e21ae311d40cd313575f18a934798e8a30a8..898c15fa68cda845ab62826e67bec29d65ff616f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Traceback.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Traceback.java @@ -33,7 +33,7 @@ import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "traceback", kind = INTERNAL, parameterNames = {"x"}, behavior = COMPLEX) -public abstract class Traceback extends RBuiltinNode { +public abstract class Traceback extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(Traceback.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java index f9c7bf4af7be07a22ab8a39d1f214ec0325b04e5..db4fa2a7fa41ad40cb1ac8117e331075c79ba5be 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java @@ -32,7 +32,6 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAt import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.profile.VectorLengthProfile; -import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RComplex; @@ -50,7 +49,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.nodes.RBaseNode; @RBuiltin(name = "t.default", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) -public abstract class Transpose extends RBuiltinNode { +public abstract class Transpose extends RBuiltinNode.Arg1 { private final BranchProfile hasDimNamesProfile = BranchProfile.create(); private final ConditionProfile isMatrixProfile = ConditionProfile.createBinaryProfile(); @@ -82,7 +81,7 @@ public abstract class Transpose extends RBuiltinNode { int secondDim; if (isMatrixProfile.profile(vector.isMatrix())) { if (getDimNode == null) { - CompilerDirectives.transferToInterpreter(); + CompilerDirectives.transferToInterpreterAndInvalidate(); getDimNode = insert(GetDimAttributeNode.create()); } int[] dims = getDimNode.getDimensions(vector); @@ -161,6 +160,6 @@ public abstract class Transpose extends RBuiltinNode { @Fallback protected RVector<?> transpose(@SuppressWarnings("unused") Object x) { - throw RError.error(RError.SHOW_CALLER, Message.ARGUMENT_NOT_MATRIX); + throw error(Message.ARGUMENT_NOT_MATRIX); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java index 9839f2e54c92dd1172cd6c1df3c1f38ca1ef2518..62eb8e262084a42cbc86ff7471bc9eafb87fdd00 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java @@ -307,7 +307,7 @@ public class TrigExpFunctions { @Override public RComplex op(double re, double im) { - throw RError.error(this, RError.Message.UNIMPLEMENTED_COMPLEX_FUN); + throw error(RError.Message.UNIMPLEMENTED_COMPLEX_FUN); } } @@ -489,7 +489,7 @@ public class TrigExpFunctions { * the {@code int} forms to {@code double}. */ @RBuiltin(name = "atan2", kind = INTERNAL, parameterNames = {"y", "x"}, behavior = PURE) - public abstract static class Atan2 extends RBuiltinNode { + public abstract static class Atan2 extends RBuiltinNode.Arg2 { private final NACheck yNACheck = NACheck.create(); private final NACheck xNACheck = NACheck.create(); @@ -565,13 +565,17 @@ public class TrigExpFunctions { profile); } - @Fallback + @Specialization(guards = {"!isDouble(x) || !isDouble(y)"}) @TruffleBoundary protected Object atan2(Object x, Object y) { if (x instanceof RAbstractComplexVector || y instanceof RAbstractComplexVector) { throw RInternalError.unimplemented("atan2 for complex values"); } - throw RError.error(this, RError.Message.NON_NUMERIC_MATH); + throw error(RError.Message.NON_NUMERIC_MATH); + } + + protected static boolean isDouble(Object x) { + return x instanceof Double || x instanceof RAbstractDoubleVector; } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java index 759597b4bcf5180f1955d47e6d3bcb2041856261..6f499ded2d781c258e95c69f223582d9d1d8a810 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java @@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory; @RBuiltin(name = "trunc", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE) -public abstract class Trunc extends RBuiltinNode { +public abstract class Trunc extends RBuiltinNode.Arg1 { private static final UnaryArithmeticFactory TRUNC = TruncArithmetic::new; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Typeof.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Typeof.java index 1366ac09fab02734ec974acab00d35836b115e31..4a694e99a52c6bb3f56f1bccfb161c9bbb836dbc 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Typeof.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Typeof.java @@ -32,7 +32,7 @@ import com.oracle.truffle.r.nodes.unary.TypeofNodeGen; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "typeof", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) -public abstract class Typeof extends RBuiltinNode { +public abstract class Typeof extends RBuiltinNode.Arg1 { @Child private TypeofNode typeofNode = TypeofNodeGen.create(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java index 04288a4970a4ee6953ef51996511f9d076172ed3..54fcb5fded17eb70aa2513ba8d2cdca5212772b2 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java @@ -29,13 +29,13 @@ import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "unclass", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) -public abstract class UnClass extends RBuiltinNode { +public abstract class UnClass extends RBuiltinNode.Arg1 { private final BranchProfile objectProfile = BranchProfile.create(); private final BranchProfile shareableProfile = BranchProfile.create(); static { Casts casts = new Casts(UnClass.class); - casts.arg("x").asAttributable(true, true, true); + casts.arg("x").mustNotBeMissing().asAttributable(true, true, true); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java index 56cad49e98b51266daf2922badc316f2ccd52ffd..d807a19e440953061b3c00bf501179c845f61908 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java @@ -23,7 +23,8 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyList; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalFalse; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -32,12 +33,14 @@ import java.util.Arrays; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.Collections.NonRecursiveHashSet; import com.oracle.truffle.r.runtime.Collections.NonRecursiveHashSetDouble; 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.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RComplex; @@ -57,13 +60,12 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "unique", kind = INTERNAL, parameterNames = {"x", "incomparables", "fromLast", "nmax"}, behavior = PURE) // TODO A more efficient implementation is in order; GNU R uses hash tables so perhaps we should // consider using one of the existing libraries that offer hash table implementations for primitive // types -public abstract class Unique extends RBuiltinNode { +public abstract class Unique extends RBuiltinNode.Arg4 { private static final long BIG_THRESHOLD = 100; @@ -72,12 +74,12 @@ public abstract class Unique extends RBuiltinNode { static { Casts casts = new Casts(Unique.class); // these are similar to those in DuplicatedFunctions.java - casts.arg("x").defaultError(RError.SHOW_CALLER, RError.Message.APPLIES_TO_VECTORS, "unique()").allowNull().mustBe(abstractVectorValue()).asVector(); + casts.arg("x").defaultError(RError.Message.APPLIES_TO_VECTORS, "unique()").allowNull().mustBe(abstractVectorValue()).asVector(); // not much more can be done for incomparables as it is either a vector of incomparable // values or a (single) logical value // TODO: coercion error must be handled by specialization as it depends on type of x (much // like in duplicated) - casts.arg("incomparables").mapNull(emptyList()).asVector(true); + casts.arg("incomparables").mustBe(logicalValue()).asLogicalVector().findFirst().mustBe(logicalFalse(), Message.GENERIC, "Handling of 'incomparables' parameter in unique is not implemented."); casts.arg("fromLast").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE); // currently not supported and not tested, but NA is a correct value (the same for empty // vectors) whereas 0 is not (throws an error) @@ -86,13 +88,16 @@ public abstract class Unique extends RBuiltinNode { @SuppressWarnings("unused") @Specialization - protected RNull doUnique(RNull vec, RAbstractVector incomparables, byte fromLast, int nmax) { + protected RNull doUnique(RNull vec, byte incomparables, byte fromLast, int nmax) { return vec; } @SuppressWarnings("unused") - @Specialization - protected RStringVector doUnique(RAbstractStringVector vec, RAbstractVector incomparables, byte fromLast, int nmax) { + @Specialization(guards = "vecIn.getClass() == vecClass") + protected RStringVector doUniqueCachedString(RAbstractStringVector vecIn, byte incomparables, byte fromLast, int nmax, + @Cached("vecIn.getClass()") Class<? extends RAbstractStringVector> vecClass) { + RAbstractStringVector vec = vecClass.cast(vecIn); + reportWork(vec.getLength()); if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) { NonRecursiveHashSet<String> set = new NonRecursiveHashSet<>(vec.getLength()); String[] data = new String[vec.getLength()]; @@ -118,6 +123,11 @@ public abstract class Unique extends RBuiltinNode { } } + @Specialization(replaces = "doUniqueCachedString") + protected RStringVector doUnique(RAbstractStringVector vec, byte incomparables, byte fromLast, int nmax) { + return doUniqueCachedString(vec, incomparables, fromLast, nmax, RAbstractStringVector.class); + } + // these are intended to stay private as they will go away once we figure out which external // library to use @@ -145,9 +155,7 @@ public abstract class Unique extends RBuiltinNode { public int[] toArray() { int[] newArray = new int[index]; - for (int i = 0; i < index; i++) { - newArray[i] = backingArray[i]; - } + System.arraycopy(backingArray, 0, newArray, 0, index); return newArray; } } @@ -176,9 +184,7 @@ public abstract class Unique extends RBuiltinNode { public double[] toArray() { double[] newArray = new double[index]; - for (int i = 0; i < index; i++) { - newArray[i] = backingArray[i]; - } + System.arraycopy(backingArray, 0, newArray, 0, index); return newArray; } } @@ -208,9 +214,7 @@ public abstract class Unique extends RBuiltinNode { public double[] toArray() { double[] newArray = new double[index]; - for (int i = 0; i < index; i++) { - newArray[i] = backingArray[i]; - } + System.arraycopy(backingArray, 0, newArray, 0, index); return newArray; } } @@ -239,16 +243,17 @@ public abstract class Unique extends RBuiltinNode { public byte[] toArray() { byte[] newArray = new byte[index]; - for (int i = 0; i < index; i++) { - newArray[i] = backingArray[i]; - } + System.arraycopy(backingArray, 0, newArray, 0, index); return newArray; } } @SuppressWarnings("unused") - @Specialization - protected RIntVector doUnique(RAbstractIntVector vec, RAbstractVector incomparables, byte fromLast, int nmax) { + @Specialization(guards = "vecIn.getClass() == vecClass") + protected RIntVector doUniqueCached(RAbstractIntVector vecIn, byte incomparables, byte fromLast, int nmax, + @Cached("vecIn.getClass()") Class<? extends RAbstractIntVector> vecClass) { + RAbstractIntVector vec = vecClass.cast(vecIn); + reportWork(vec.getLength()); if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) { NonRecursiveHashSetInt set = new NonRecursiveHashSetInt(); int[] data = new int[16]; @@ -275,9 +280,14 @@ public abstract class Unique extends RBuiltinNode { } } + @Specialization(replaces = "doUniqueCached") + protected RIntVector doUnique(RAbstractIntVector vec, byte incomparables, byte fromLast, int nmax) { + return doUniqueCached(vec, incomparables, fromLast, nmax, RAbstractIntVector.class); + } + @SuppressWarnings("unused") @Specialization(guards = "lengthOne(list)") - protected RList doUniqueL1(RList list, RAbstractVector incomparables, byte fromLast, int nmax) { + protected RList doUniqueL1(RList list, byte incomparables, byte fromLast, int nmax) { return (RList) list.copyDropAttributes(); } @@ -294,7 +304,8 @@ public abstract class Unique extends RBuiltinNode { @SuppressWarnings("unused") @Specialization(guards = "!lengthOne(list)") @TruffleBoundary - protected RList doUnique(RList list, RAbstractVector incomparables, byte fromLast, int nmax) { + protected RList doUnique(RList list, byte incomparables, byte fromLast, int nmax) { + reportWork(list.getLength()); /* * Brute force, as manual says: Using this for lists is potentially slow, especially if the * elements are not atomic vectors (see vector) or differ only in their attributes. In the @@ -373,7 +384,8 @@ public abstract class Unique extends RBuiltinNode { @SuppressWarnings("unused") @Specialization - protected RDoubleVector doUnique(RAbstractDoubleVector vec, RAbstractVector incomparables, byte fromLast, int nmax) { + protected RDoubleVector doUnique(RAbstractDoubleVector vec, byte incomparables, byte fromLast, int nmax) { + reportWork(vec.getLength()); if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) { NonRecursiveHashSetDouble set = new NonRecursiveHashSetDouble(vec.getLength()); double[] data = new double[vec.getLength()]; @@ -399,7 +411,8 @@ public abstract class Unique extends RBuiltinNode { @SuppressWarnings("unused") @Specialization - protected RLogicalVector doUnique(RAbstractLogicalVector vec, RAbstractVector incomparables, byte fromLast, int nmax) { + protected RLogicalVector doUnique(RAbstractLogicalVector vec, byte incomparables, byte fromLast, int nmax) { + reportWork(vec.getLength()); ByteArray dataList = new ByteArray(vec.getLength()); for (int i = 0; i < vec.getLength(); i++) { byte val = vec.getDataAt(i); @@ -412,7 +425,8 @@ public abstract class Unique extends RBuiltinNode { @SuppressWarnings("unused") @Specialization - protected RComplexVector doUnique(RAbstractComplexVector vec, RAbstractVector incomparables, byte fromLast, int nmax) { + protected RComplexVector doUnique(RAbstractComplexVector vec, byte incomparables, byte fromLast, int nmax) { + reportWork(vec.getLength()); if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) { NonRecursiveHashSet<RComplex> set = new NonRecursiveHashSet<>(vec.getLength()); double[] data = new double[vec.getLength() * 2]; @@ -439,7 +453,8 @@ public abstract class Unique extends RBuiltinNode { @SuppressWarnings("unused") @Specialization - protected RRawVector doUnique(RAbstractRawVector vec, RAbstractVector incomparables, byte fromLast, int nmax) { + protected RRawVector doUnique(RAbstractRawVector vec, byte incomparables, byte fromLast, int nmax) { + reportWork(vec.getLength()); if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) { NonRecursiveHashSet<RRaw> set = new NonRecursiveHashSet<>(vec.getLength()); byte[] data = new byte[vec.getLength()]; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java index 67b2bbd51707a4e5a18fa48104f2401aecb7404c..aeee8fa4fe146c22d85af9c824d5cb1261411b31 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java @@ -27,6 +27,7 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.UnlistNodeGen.RecursiveLengthNodeGen; import com.oracle.truffle.r.nodes.unary.PrecedenceNode; import com.oracle.truffle.r.nodes.unary.PrecedenceNodeGen; +import com.oracle.truffle.r.runtime.RDispatch; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -40,12 +41,13 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPairList; import com.oracle.truffle.r.runtime.data.RRaw; import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.RTypes; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -@RBuiltin(name = "unlist", kind = INTERNAL, parameterNames = {"x", "recursive", "use.names"}, behavior = PURE) -public abstract class Unlist extends RBuiltinNode { +@RBuiltin(name = "unlist", kind = INTERNAL, dispatch = RDispatch.INTERNAL_GENERIC, parameterNames = {"x", "recursive", "use.names"}, behavior = PURE) +public abstract class Unlist extends RBuiltinNode.Arg3 { // portions of the algorithm were transcribed from GNU R @@ -96,6 +98,11 @@ public abstract class Unlist extends RBuiltinNode { return 1; } + @Specialization + protected int getLength(@SuppressWarnings("unused") RSymbol s) { + return 1; + } + @Specialization(guards = "!isVectorList(vector)") protected int getLength(RAbstractVector vector) { return vector.getLength(); @@ -707,14 +714,14 @@ public abstract class Unlist extends RBuiltinNode { } else if (dataAtAsObject instanceof Double) { double result = unlistValueDouble(dataAtAsObject); if (RRuntime.isNA(result)) { - return RRuntime.createComplexNA(); + return RComplex.createNA(); } else { return RDataFactory.createComplex(result, 0.0); } } else { int result = unlistValueInt(dataAtAsObject); if (RRuntime.isNA(result)) { - return RRuntime.createComplexNA(); + return RComplex.createNA(); } else { return RDataFactory.createComplex(result, 0.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 a9d87f4e4978b08bb04873a4f85121f5632530ef..1b8e654595860dd72bb9c1a41276a552536ace64 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 @@ -23,7 +23,6 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; -import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; import static com.oracle.truffle.r.runtime.RError.Message.MUST_BE_NONNULL_STRING; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -33,10 +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.dsl.TypeSystemReference; import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.profiles.BranchProfile; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.nodes.attributes.RemoveAttributeNode; import com.oracle.truffle.r.nodes.attributes.SetAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode; @@ -49,6 +45,7 @@ import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen; import com.oracle.truffle.r.nodes.unary.CastListNode; 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.RRuntime; import com.oracle.truffle.r.runtime.Utils; @@ -63,9 +60,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "attr<-", kind = PRIMITIVE, parameterNames = {"x", "which", "value"}, behavior = PURE) -public abstract class UpdateAttr extends RBuiltinNode { - - private final BranchProfile errorProfile = BranchProfile.create(); +public abstract class UpdateAttr extends RBuiltinNode.Arg3 { @Child private UpdateNames updateNames; @Child private UpdateDimNames updateDimNames; @@ -79,7 +74,6 @@ public abstract class UpdateAttr extends RBuiltinNode { @Child private InternStringNode intern = InternStringNodeGen.create(); - @TypeSystemReference(EmptyTypeSystemFlatLayout.class) public abstract static class InternStringNode extends Node { public abstract String execute(String value); @@ -102,7 +96,7 @@ public abstract class UpdateAttr extends RBuiltinNode { // Note: cannot check 'attributability' easily because atomic values, e.g int, are not // RAttributable. casts.arg("x"); // disallows null - casts.arg("which").defaultError(SHOW_CALLER, MUST_BE_NONNULL_STRING, "name").mustBe(stringValue()).asStringVector().findFirst(); + casts.arg("which").defaultError(MUST_BE_NONNULL_STRING, "name").mustBe(stringValue()).asStringVector().findFirst(); } private RAbstractContainer updateNames(RAbstractContainer container, Object o) { @@ -126,7 +120,7 @@ public abstract class UpdateAttr extends RBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); castInteger = insert(CastIntegerNodeGen.create(true, false, false)); } - return (RAbstractIntVector) castInteger.execute(vector); + return (RAbstractIntVector) castInteger.doCast(vector); } private RAbstractVector castVector(Object value) { @@ -134,14 +128,15 @@ public abstract class UpdateAttr extends RBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); castVector = insert(CastToVectorNodeGen.create(false)); } - return (RAbstractVector) castVector.execute(value); + return (RAbstractVector) castVector.doCast(value); } @Specialization protected RAbstractContainer updateAttr(RAbstractContainer container, String name, RNull value, - @Cached("create()") RemoveAttributeNode removeAttrNode) { + @Cached("create()") RemoveAttributeNode removeAttrNode, + @Cached("create()") GetNonSharedNode nonShared) { String internedName = intern.execute(name); - RAbstractContainer result = (RAbstractContainer) container.getNonShared(); + RAbstractContainer result = ((RAbstractContainer) nonShared.execute(container)).materialize(); // the name is interned, so identity comparison is sufficient if (internedName == RRuntime.DIM_ATTR_KEY) { if (setDimNode == null) { @@ -179,20 +174,20 @@ public abstract class UpdateAttr extends RBuiltinNode { } else if (value instanceof String) { return RDataFactory.createStringVector((String) value); } else { - throw RError.error(RError.SHOW_CALLER2, RError.Message.SET_INVALID_CLASS_ATTR); + throw RError.error(RError.SHOW_CALLER, RError.Message.SET_INVALID_CLASS_ATTR); } } - @Specialization(guards = "!nullValue(value)") - protected RAbstractContainer updateAttr(RAbstractContainer container, String name, Object value) { + @Specialization(guards = "!isRNull(value)") + protected RAbstractContainer updateAttr(RAbstractContainer container, String name, Object value, + @Cached("create()") GetNonSharedNode nonShared) { String internedName = intern.execute(name); - RAbstractContainer result = (RAbstractContainer) container.getNonShared(); + RAbstractContainer result = ((RAbstractContainer) nonShared.execute(container)).materialize(); // the name is interned, so identity comparison is sufficient if (internedName == RRuntime.DIM_ATTR_KEY) { RAbstractIntVector dimsVector = castInteger(castVector(value)); if (dimsVector.getLength() == 0) { - errorProfile.enter(); - throw RError.error(this, RError.Message.LENGTH_ZERO_DIM_INVALID); + throw error(RError.Message.LENGTH_ZERO_DIM_INVALID); } if (setDimNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -228,12 +223,6 @@ public abstract class UpdateAttr extends RBuiltinNode { return result; } - // the guard is necessary as RNull and Object cannot be distinguished in case of multiple - // specializations, such as in: x<-1; attr(x, "dim")<-1; attr(x, "dim")<-NULL - protected boolean nullValue(Object value) { - return value == RNull.instance; - } - /** * All other, non-performance centric, {@link RAttributable} types. */ diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java index b3df6a98a0def6db42cfd3a21ddd4b2798d1ba45..c28a5e5175b19cd4c05ea67391d872e3e04005b1 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java @@ -30,6 +30,8 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.attributes.RemoveAttributeNode; @@ -43,6 +45,7 @@ import com.oracle.truffle.r.nodes.unary.CastIntegerNode; import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen; 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.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -51,13 +54,12 @@ import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.RTypesGen; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "attributes<-", kind = PRIMITIVE, parameterNames = {"obj", "value"}, behavior = PURE) -public abstract class UpdateAttributes extends RBuiltinNode { +public abstract class UpdateAttributes extends RBuiltinNode.Arg2 { private final ConditionProfile numAttributesProfile = ConditionProfile.createBinaryProfile(); @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create(); @@ -103,7 +105,7 @@ public abstract class UpdateAttributes extends RBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); castInteger = insert(CastIntegerNodeGen.create(true, false, false)); } - return (RAbstractIntVector) castInteger.execute(vector); + return (RAbstractIntVector) castInteger.doCast(vector); } private RAbstractVector castVector(Object value) { @@ -111,24 +113,26 @@ public abstract class UpdateAttributes extends RBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); castVector = insert(CastToVectorNodeGen.create(false)); } - return (RAbstractVector) castVector.execute(value); + return (RAbstractVector) castVector.doCast(value); } @Specialization - protected RAbstractContainer updateAttributes(RAbstractContainer abstractContainer, @SuppressWarnings("unused") RNull list) { - RAbstractContainer resultVector = (RAbstractContainer) abstractContainer.getNonShared(); + protected RAbstractContainer updateAttributes(RAbstractContainer abstractContainer, @SuppressWarnings("unused") RNull list, + @Cached("create()") GetNonSharedNode nonShared) { + RAbstractContainer resultVector = ((RAbstractContainer) nonShared.execute(abstractContainer)).materialize(); resultVector.resetAllAttributes(true); return resultVector; } @Specialization - protected RAbstractContainer updateAttributes(RAbstractContainer container, RList list) { + protected RAbstractContainer updateAttributes(RAbstractContainer container, RList list, + @Cached("create()") GetNonSharedNode nonShared) { Object listNamesObject = getNamesNode.getNames(list); if (listNamesObject == null || listNamesObject == RNull.instance) { - throw RError.error(this, RError.Message.ATTRIBUTES_NAMED); + throw error(RError.Message.ATTRIBUTES_NAMED); } RStringVector listNames = (RStringVector) listNamesObject; - RAbstractContainer result = (RAbstractContainer) container.getNonShared(); + RAbstractContainer result = ((RAbstractContainer) nonShared.execute(container)).materialize(); if (numAttributesProfile.profile(list.getLength() == 0)) { result.resetAllAttributes(true); } else { @@ -140,7 +144,7 @@ public abstract class UpdateAttributes extends RBuiltinNode { } // has to be reported if no other name is undefined if (listNames.getDataAt(0).equals(RRuntime.NAMES_ATTR_EMPTY_VALUE)) { - throw RError.error(this, RError.Message.ZERO_LENGTH_VARIABLE); + throw error(RError.Message.ZERO_LENGTH_VARIABLE); } // set the dim attribute first setDimAttribute(result, list); @@ -158,7 +162,7 @@ public abstract class UpdateAttributes extends RBuiltinNode { for (int i = 1; i < length; i++) { String attrName = listNames.getDataAt(i); if (attrName.equals(RRuntime.NAMES_ATTR_EMPTY_VALUE)) { - throw RError.error(this, RError.Message.ALL_ATTRIBUTES_NAMES, i + 1); + throw error(RError.Message.ALL_ATTRIBUTES_NAMES, i + 1); } } } @@ -182,7 +186,7 @@ public abstract class UpdateAttributes extends RBuiltinNode { } else { RAbstractIntVector dimsVector = castInteger(castVector(value)); if (dimsVector.getLength() == 0) { - throw RError.error(this, RError.Message.LENGTH_ZERO_DIM_INVALID); + throw error(RError.Message.LENGTH_ZERO_DIM_INVALID); } setDimNode.setDimensions(result, dimsVector.materialize().getDataCopy()); } @@ -206,7 +210,7 @@ public abstract class UpdateAttributes extends RBuiltinNode { res = updateDimNames(res, value); } else if (attrName.equals(RRuntime.CLASS_ATTR_KEY)) { if (setClassNode == null) { - CompilerDirectives.transferToInterpreter(); + CompilerDirectives.transferToInterpreterAndInvalidate(); setClassNode = insert(SetClassAttributeNode.create()); } if (value == RNull.instance) { @@ -223,7 +227,7 @@ public abstract class UpdateAttributes extends RBuiltinNode { } else { if (value == RNull.instance) { if (removeAttrNode == null) { - CompilerDirectives.transferToInterpreter(); + CompilerDirectives.transferToInterpreterAndInvalidate(); removeAttrNode = insert(RemoveAttributeNode.create()); } removeAttrNode.execute(res, attrName); @@ -239,54 +243,40 @@ public abstract class UpdateAttributes extends RBuiltinNode { return res; } - protected static boolean isAbstractContainer(Object value) { - return RTypesGen.isImplicitRAbstractContainer(value); - } - /** * All other, non-performance centric, {@link RAttributable} types, or error case for RNull * value. */ - @Specialization(guards = {"!isAbstractContainer(o)"}) + @Fallback @TruffleBoundary - protected Object doOtherNull(Object o, @SuppressWarnings("unused") RNull operand) { + protected Object doOtherNull(Object o, Object operand) { checkAttributable(o); Object obj = getNonShared(o); RAttributable attrObj = (RAttributable) obj; attrObj.removeAllAttributes(); - attrObj.setClassAttr(null); - return obj; - } - /** - * All other, non-performance centric, {@link RAttributable} types, or error case for list - * value. - */ - @Specialization(guards = {"!isAbstractContainer(o)"}) - @TruffleBoundary - protected Object doOtherList(Object o, RList operand) { - checkAttributable(o); - Object obj = getNonShared(o); - RAttributable attrObj = (RAttributable) obj; - attrObj.removeAllAttributes(); - RStringVector listNames = operand.getNames(); - if (listNames == null) { - throw RError.error(this, RError.Message.ATTRIBUTES_NAMED); - } - for (int i = 0; i < operand.getLength(); i++) { - String attrName = listNames.getDataAt(i); - if (attrName == null) { - throw RError.error(this, RError.Message.ATTRIBUTES_NAMED); + if (operand == RNull.instance) { + attrObj.setClassAttr(null); + } else { + RList list = (RList) operand; + RStringVector listNames = list.getNames(); + if (listNames == null) { + throw error(RError.Message.ATTRIBUTES_NAMED); } - if (RRuntime.CLASS_ATTR_KEY.equals(attrName)) { - Object attrValue = operand.getDataAt(i); - if (attrValue == null) { - throw RError.error(this, RError.Message.SET_INVALID_CLASS_ATTR); + for (int i = 0; i < list.getLength(); i++) { + String attrName = listNames.getDataAt(i); + if (attrName == null) { + throw error(RError.Message.ATTRIBUTES_NAMED); + } + if (RRuntime.CLASS_ATTR_KEY.equals(attrName)) { + Object attrValue = list.getDataAt(i); + if (attrValue == null) { + throw error(RError.Message.SET_INVALID_CLASS_ATTR); + } + attrObj.setClassAttr(UpdateAttr.convertClassAttrFromObject(attrValue)); + } else { + attrObj.setAttr(attrName.intern(), list.getDataAt(i)); } - - attrObj.setClassAttr(UpdateAttr.convertClassAttrFromObject(attrValue)); - } else { - attrObj.setAttr(attrName.intern(), operand.getDataAt(i)); } } return obj; @@ -294,7 +284,7 @@ public abstract class UpdateAttributes extends RBuiltinNode { private void checkAttributable(Object obj) { if (!(obj instanceof RAttributable)) { - throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); + throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java index 7fd8850a961d0376793af976ff8af21e38e979f4..b32345f7ff7d7d80c006a9356eaf8cdabfcf0617 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java @@ -11,6 +11,7 @@ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -42,7 +43,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; @RBuiltin(name = "class<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, behavior = PURE) -public abstract class UpdateClass extends RBuiltinNode { +public abstract class UpdateClass extends RBuiltinNode.Arg2 { protected static final int CACHE_LIMIT = 2; @@ -52,8 +53,8 @@ public abstract class UpdateClass extends RBuiltinNode { static { Casts casts = new Casts(UpdateClass.class); - casts.arg("x"); // disallows null - casts.arg("value").asStringVector(); + casts.arg("x").mustBe(missingValue().not(), RError.Message.ARGUMENT_EMPTY, 1); + casts.arg("value").mustBe(missingValue().not(), RError.Message.ARGUMENT_EMPTY, 2).asStringVector(); } @Specialization @@ -64,6 +65,11 @@ public abstract class UpdateClass extends RBuiltinNode { return result; } + @Specialization + protected Object setClass(@SuppressWarnings("unused") RNull arg, @SuppressWarnings("unused") Object className) { + throw error(RError.Message.SET_ATTRIBUTES_ON_NULL); + } + @Specialization(limit = "CACHE_LIMIT", guards = "cachedClassName == className") protected Object setClassCached(RAbstractContainer arg, @SuppressWarnings("unused") String className, @Cached("className") String cachedClassName, @@ -106,14 +112,14 @@ public abstract class UpdateClass extends RBuiltinNode { } CompilerDirectives.transferToInterpreter(); int[] dimensions = resultVector.getDimensions(); - throw RError.error(this, RError.Message.NOT_A_MATRIX_UPDATE_CLASS, dimensions == null ? 0 : dimensions.length); + throw error(RError.Message.NOT_A_MATRIX_UPDATE_CLASS, dimensions == null ? 0 : dimensions.length); } if (RType.Array.getName().equals(className)) { if (resultVector.isArray()) { return setClass(resultVector, RNull.instance); } CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.NOT_ARRAY_UPDATE_CLASS); + throw error(RError.Message.NOT_ARRAY_UPDATE_CLASS); } } @@ -197,7 +203,7 @@ public abstract class UpdateClass extends RBuiltinNode { private void initCastTypeNode() { if (castTypeNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - castTypeNode = insert(CastTypeNodeGen.create(null, null)); + castTypeNode = insert(CastTypeNodeGen.create()); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java index 867c09bfd9d94bd70f5967e5081c10ab2e3c58cd..3e3c60210e69161060da326c797a8ad43bdc1274 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java @@ -44,7 +44,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "dim<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, behavior = PURE) -public abstract class UpdateDim extends RBuiltinNode { +public abstract class UpdateDim extends RBuiltinNode.Arg2 { @Child private ReuseNonSharedNode reuse = ReuseNonSharedNode.create(); @@ -56,7 +56,7 @@ public abstract class UpdateDim extends RBuiltinNode { @Specialization protected RAbstractVector updateDim(RAbstractVector vector, @SuppressWarnings("unused") RNull dimensions) { - RVector<?> result = ((RAbstractVector) reuse.execute(vector)).materialize(); + RVector<?> result = reuse.execute(vector); result.resetDimensions(null); return result; } @@ -69,7 +69,7 @@ public abstract class UpdateDim extends RBuiltinNode { RIntVector dimensionsMaterialized = dimensions.materialize(); int[] dimsData = dimensionsMaterialized.getDataCopy(); RVector.verifyDimensions(vector.getLength(), dimsData, this); - RVector<?> result = ((RAbstractVector) reuse.execute(vector)).materialize(); + RVector<?> result = reuse.execute(vector); removeNames.execute(result); DynamicObject attrs = result.getAttributes(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java index 439c1b4a24a87890249021686aca040f5b847443..080ad9a807a07da1f74d8f1518eb04f4031685d3 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java @@ -37,6 +37,7 @@ import com.oracle.truffle.r.nodes.unary.CastStringNode; import com.oracle.truffle.r.nodes.unary.CastStringNodeGen; 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.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -46,7 +47,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "dimnames<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, dispatch = INTERNAL_GENERIC, behavior = PURE) -public abstract class UpdateDimNames extends RBuiltinNode { +public abstract class UpdateDimNames extends RBuiltinNode.Arg2 { protected static final String DIMNAMES_ATTR_KEY = RRuntime.DIMNAMES_ATTR_KEY; @@ -64,7 +65,7 @@ public abstract class UpdateDimNames extends RBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); castStringNode = insert(CastStringNodeGen.create(true, true, true)); } - return castStringNode.execute(o); + return castStringNode.doCast(o); } private RAbstractVector castVector(Object value) { @@ -72,7 +73,7 @@ public abstract class UpdateDimNames extends RBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); castVectorNode = insert(CastToVectorNodeGen.create(false)); } - return ((RAbstractVector) castVectorNode.execute(value)).materialize(); + return ((RAbstractVector) castVectorNode.doCast(value)); } public abstract RAbstractContainer executeRAbstractContainer(RAbstractContainer container, Object o); @@ -94,22 +95,25 @@ public abstract class UpdateDimNames extends RBuiltinNode { @Specialization protected RAbstractContainer updateDimnamesNull(RAbstractContainer container, @SuppressWarnings("unused") RNull list, - @Cached("createDimNames()") RemoveFixedAttributeNode remove) { - RAbstractContainer result = (RAbstractContainer) container.getNonShared(); + @Cached("createDimNames()") RemoveFixedAttributeNode remove, + @Cached("create()") GetNonSharedNode nonShared) { + RAbstractContainer result = ((RAbstractContainer) nonShared.execute(container)).materialize(); remove.execute(result); return result; } @Specialization(guards = "list.getLength() == 0") protected RAbstractContainer updateDimnamesEmpty(RAbstractContainer container, @SuppressWarnings("unused") RList list, - @Cached("createDimNames()") RemoveFixedAttributeNode remove) { - return updateDimnamesNull(container, RNull.instance, remove); + @Cached("createDimNames()") RemoveFixedAttributeNode remove, + @Cached("create()") GetNonSharedNode nonShared) { + return updateDimnamesNull(container, RNull.instance, remove, nonShared); } @Specialization(guards = "list.getLength() > 0") protected RAbstractContainer updateDimnames(RAbstractContainer container, RList list, - @Cached("create()") SetDimNamesAttributeNode setDimNamesNode) { - RAbstractContainer result = (RAbstractContainer) container.getNonShared(); + @Cached("create()") SetDimNamesAttributeNode setDimNamesNode, + @Cached("create()") GetNonSharedNode nonShared) { + RAbstractContainer result = ((RAbstractContainer) nonShared.execute(container)).materialize(); setDimNamesNode.setDimNames(result, convertToListOfStrings(list)); return result; } @@ -117,6 +121,6 @@ public abstract class UpdateDimNames extends RBuiltinNode { @Specialization(guards = "!isRList(c)") protected RAbstractContainer updateDimnamesError(@SuppressWarnings("unused") RAbstractContainer container, @SuppressWarnings("unused") Object c) { CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.DIMNAMES_LIST); + throw error(RError.Message.DIMNAMES_LIST); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLength.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLength.java index 38199269d78caf344dda3e5852a7be155b2c1586..74ada4082119f8221a3d500145dacaeac3972d72 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLength.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLength.java @@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; @RBuiltin(name = "length<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, dispatch = INTERNAL_GENERIC, behavior = PURE) -public abstract class UpdateLength extends RBuiltinNode { +public abstract class UpdateLength extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(UpdateLength.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java index fd018457e0b7ae7593f0fb9eda653088196bd516..3083e952de63ead07a5a965dc80f1da942dc98d6 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java @@ -20,7 +20,6 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.attributes.RemoveFixedAttributeNode; import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -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.builtins.RBuiltin; @@ -29,7 +28,7 @@ import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "levels<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, dispatch = INTERNAL_GENERIC, behavior = PURE) -public abstract class UpdateLevels extends RBuiltinNode { +public abstract class UpdateLevels extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(UpdateLevels.class); @@ -67,6 +66,6 @@ public abstract class UpdateLevels extends RBuiltinNode { @Specialization(guards = "!isRNull(levels)") protected RAbstractVector updateLevels(@SuppressWarnings("unused") RNull vector, @SuppressWarnings("unused") Object levels) { - throw RError.error(this, Message.SET_ATTRIBUTES_ON_NULL); + throw error(Message.SET_ATTRIBUTES_ON_NULL); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java index afefd3a53d9906356b15807444a5985e6a550171..c58e054d13d7f8a640da45c7c0c134c4243714f8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java @@ -28,11 +28,12 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.unary.CastStringNode; import com.oracle.truffle.r.nodes.unary.CastStringNodeGen; -import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.nodes.unary.GetNonSharedNode; import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -42,7 +43,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "names<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, dispatch = INTERNAL_GENERIC, behavior = PURE) -public abstract class UpdateNames extends RBuiltinNode { +public abstract class UpdateNames extends RBuiltinNode.Arg2 { @Child private CastStringNode castStringNode; @@ -62,10 +63,11 @@ public abstract class UpdateNames extends RBuiltinNode { @Specialization @TruffleBoundary - protected RAbstractContainer updateNames(RAbstractContainer container, Object names) { + protected RAbstractContainer updateNames(RAbstractContainer container, Object names, + @Cached("create()") GetNonSharedNode nonShared) { Object newNames = castString(names); + RAbstractContainer result = ((RAbstractContainer) nonShared.execute(container)).materialize(); if (newNames == RNull.instance) { - RAbstractContainer result = (RAbstractContainer) container.getNonShared(); result.setNames(null); return result; } @@ -76,17 +78,15 @@ public abstract class UpdateNames extends RBuiltinNode { } else { stringVector = (RStringVector) ((RAbstractVector) newNames).materialize().copyDropAttributes(); } - RAbstractContainer result = (RAbstractContainer) container.getNonShared(); if (stringVector.getLength() < result.getLength()) { stringVector = (RStringVector) stringVector.copyResized(result.getLength(), true); } else if (stringVector.getLength() > result.getLength()) { - throw RError.error(this, Message.NAMES_LONGER, stringVector.getLength(), result.getLength()); + throw error(Message.NAMES_LONGER, stringVector.getLength(), result.getLength()); } else if (stringVector == names) { stringVector = (RStringVector) stringVector.copy(); } if (stringVector.isTemporary()) { stringVector.incRefCount(); - } result.setNames(stringVector); return result; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java index 0ba6831d05d0ce923b21cda2912c773c0c5c3679..d161c6383775de582b12f109d93730547cc9aede 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java @@ -36,14 +36,13 @@ import com.oracle.truffle.r.nodes.unary.CastStringNodeGen; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RString; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; // oldClass<- (as opposed to class<-), simply sets the attribute (without handling "implicit" attributes) @RBuiltin(name = "oldClass<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, behavior = PURE) -public abstract class UpdateOldClass extends RBuiltinNode { +public abstract class UpdateOldClass extends RBuiltinNode.Arg2 { @Child private CastStringNode castStringNode; @Child private SetClassAttributeNode setClassAttributeNode = SetClassAttributeNode.create(); @@ -52,13 +51,13 @@ public abstract class UpdateOldClass extends RBuiltinNode { Casts.noCasts(UpdateOldClass.class); } - @Specialization(guards = "!isStringVector(className)") + @Specialization(guards = "!isRAbstractStringVector(className)") protected Object setOldClass(RAbstractContainer arg, RAbstractVector className) { if (className.getLength() == 0) { return setOldClass(arg, RNull.instance); } initCastStringNode(); - Object result = castStringNode.execute(className); + Object result = castStringNode.doCast(className); return setOldClass(arg, (RStringVector) result); } @@ -90,8 +89,4 @@ public abstract class UpdateOldClass extends RBuiltinNode { setClassAttributeNode.reset(result); return result; } - - protected boolean isStringVector(RAbstractVector className) { - return className.getElementClass() == RString.class; - } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java index 9dcc170b841a3627d3d383a9122823f5e6dc15f8..560b5fc442c9b3f045b699ee24fb4b268c34dd5e 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java @@ -22,14 +22,12 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.r.nodes.access.ConstantNode; import com.oracle.truffle.r.nodes.access.UpdateSlotNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; +import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen; -import com.oracle.truffle.r.nodes.function.RCallNode; -import com.oracle.truffle.r.nodes.function.WrapArgumentNode; import com.oracle.truffle.r.nodes.function.call.CallRFunctionNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RCaller; @@ -38,105 +36,91 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RPromise; +import com.oracle.truffle.r.runtime.data.RPromise.Closure; import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant; +import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; +import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @RBuiltin(name = "@<-", kind = PRIMITIVE, parameterNames = {"", "", "value"}, nonEvalArgs = 1, behavior = COMPLEX) -public abstract class UpdateSlot extends RBuiltinNode { +public abstract class UpdateSlot extends RBuiltinNode.Arg3 { - private static final ArgumentsSignature SIGNATURE = ArgumentsSignature.get("cl", "name", "valueClass"); - - @CompilationFinal private RFunction checkSlotAssignFunction; - @Child private ClassHierarchyNode objClassHierarchy; - @Child private ClassHierarchyNode valClassHierarchy; @Child private UpdateSlotNode updateSlotNode = com.oracle.truffle.r.nodes.access.UpdateSlotNodeGen.create(); - @Child private ReadVariableNode checkAtAssignmentFind = ReadVariableNode.createFunctionLookup(RSyntaxNode.INTERNAL, "checkAtAssignment"); - @Child private CallRFunctionNode checkAtAssignmentCall; - private final ConditionProfile cached = ConditionProfile.createBinaryProfile(); static { Casts casts = new Casts(UpdateSlot.class); casts.arg(0).asAttributable(true, true, true); } - protected String getName(Object nameObj) { - assert nameObj instanceof RPromise; - Object rep = ((RPromise) nameObj).getRep(); - if (rep instanceof WrapArgumentNode) { - rep = ((WrapArgumentNode) rep).getOperand(); - } - if (rep instanceof ConstantNode) { - Object val = ((ConstantNode) rep).getValue(); - if (val instanceof String) { - return (String) val; - } - if (val instanceof RSymbol) { - return ((RSymbol) val).getName(); + protected String getName(RPromise nameObj) { + Closure closure = nameObj.getClosure(); + if (closure.asSymbol() != null) { + return closure.asSymbol(); + } else if (closure.asStringConstant() != null) { + return closure.asStringConstant(); + } else { + CompilerDirectives.transferToInterpreter(); + RSyntaxElement element = closure.getExpr().asRSyntaxNode(); + assert !(element instanceof RSyntaxLookup); + if (element instanceof RSyntaxConstant) { + throw error(RError.Message.SLOT_INVALID_TYPE, Predef.typeName().apply(((RSyntaxConstant) element).getValue())); + } else { + throw error(RError.Message.SLOT_INVALID_TYPE, "language"); } - } else if (rep instanceof ReadVariableNode) { - return ((ReadVariableNode) rep).getIdentifier(); - } else if (rep instanceof RCallNode) { - throw RError.error(this, RError.Message.SLOT_INVALID_TYPE, "language"); } - // TODO: this is not quite correct, but I wonder if we even reach here (can also be - // augmented on demand) - throw RError.error(this, RError.Message.SLOT_INVALID_TYPE, nameObj.getClass().toString()); } - private void checkSlotAssign(VirtualFrame frame, Object object, String name, Object value) { - // TODO: optimize using a mechanism similar to overrides? - if (checkSlotAssignFunction == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - checkSlotAssignFunction = (RFunction) checkAtAssignmentFind.execute(frame); - } - if (checkAtAssignmentCall == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - checkAtAssignmentCall = insert(CallRFunctionNode.create(checkSlotAssignFunction.getTarget())); - } - if (objClassHierarchy == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - objClassHierarchy = insert(ClassHierarchyNodeGen.create(true, false)); - } - if (valClassHierarchy == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - valClassHierarchy = insert(ClassHierarchyNodeGen.create(true, false)); - } - RStringVector objClass = objClassHierarchy.execute(object); - RStringVector valClass = valClassHierarchy.execute(value); - RFunction currentFunction = (RFunction) checkAtAssignmentFind.execute(frame); - if (cached.profile(currentFunction == checkSlotAssignFunction)) { - // TODO: technically, someone could override checkAtAssignment function and access the - // caller, but it's rather unlikely - checkAtAssignmentCall.execute(frame, checkSlotAssignFunction, RCaller.create(frame, getOriginalCall()), null, new Object[]{objClass, name, valClass}, SIGNATURE, - checkSlotAssignFunction.getEnclosingFrame(), null); - } else { - // slow path - RContext.getEngine().evalFunction(currentFunction, frame.materialize(), RCaller.create(frame, getOriginalCall()), null, objClass, name, valClass); - } - } + public static final class CheckSlotAssignNode extends RBaseNode { - /* - * Motivation for cached version is that in the operator form (foo@bar<-baz), the name is an - * interned string which allows us to avoid longer lookup - */ - @Specialization(guards = "sameName(nameObj, nameObjCached)") - protected Object updateSlotCached(VirtualFrame frame, Object object, @SuppressWarnings("unused") Object nameObj, Object value, @SuppressWarnings("unused") @Cached("nameObj") Object nameObjCached, - @Cached("getName(nameObjCached)") String name) { - checkSlotAssign(frame, object, name, value); - return updateSlotNode.executeUpdate(object, name, value); + private static final ArgumentsSignature SIGNATURE = ArgumentsSignature.get("cl", "name", "valueClass"); + + @CompilationFinal private RFunction checkSlotAssignFunction; + @Child private ClassHierarchyNode objClassHierarchy; + @Child private ClassHierarchyNode valClassHierarchy; + @Child private ReadVariableNode checkAtAssignmentFind = ReadVariableNode.createFunctionLookup(RSyntaxNode.INTERNAL, "checkAtAssignment"); + @Child private CallRFunctionNode checkAtAssignmentCall; + + private final ConditionProfile cached = ConditionProfile.createBinaryProfile(); + + public void execute(VirtualFrame frame, Object object, String name, Object value) { + if (checkSlotAssignFunction == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + checkSlotAssignFunction = (RFunction) checkAtAssignmentFind.execute(frame); + } + if (checkAtAssignmentCall == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + checkAtAssignmentCall = insert(CallRFunctionNode.create(checkSlotAssignFunction.getTarget())); + } + if (objClassHierarchy == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + objClassHierarchy = insert(ClassHierarchyNodeGen.create(true, false)); + } + if (valClassHierarchy == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + valClassHierarchy = insert(ClassHierarchyNodeGen.create(true, false)); + } + RStringVector objClass = objClassHierarchy.execute(object); + RStringVector valClass = valClassHierarchy.execute(value); + RFunction currentFunction = (RFunction) checkAtAssignmentFind.execute(frame); + if (cached.profile(currentFunction == checkSlotAssignFunction)) { + // TODO: technically, someone could override checkAtAssignment function and access + // the caller, but it's rather unlikely + checkAtAssignmentCall.execute(frame, checkSlotAssignFunction, RCaller.createInvalid(frame), null, new Object[]{objClass, name, valClass}, SIGNATURE, + checkSlotAssignFunction.getEnclosingFrame(), null); + } else { + // slow path + RContext.getEngine().evalFunction(currentFunction, frame.materialize(), RCaller.createInvalid(frame), null, objClass, name, valClass); + } + } } - @Specialization(replaces = "updateSlotCached") - protected Object updateSlot(VirtualFrame frame, Object object, Object nameObj, Object value) { + @Specialization + protected Object updateSlot(VirtualFrame frame, Object object, RPromise nameObj, Object value, + @Cached("new()") CheckSlotAssignNode check) { String name = getName(nameObj); - checkSlotAssign(frame, object, name, value); + check.execute(frame, object, name, value); return updateSlotNode.executeUpdate(object, name, value); } - - protected boolean sameName(Object nameObj, Object nameObjCached) { - assert nameObj instanceof RPromise; - assert nameObjCached instanceof RPromise; - return ((RPromise) nameObj).getRep() == ((RPromise) nameObjCached).getRep(); - } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java index 690118997285088d23f31997c41305f015ec98c4..c33d4ddb015d8dc5b97ce7ca4815b9811aee0c6f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java @@ -18,7 +18,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.object.DynamicObject; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.attributes.ArrayAttributeNode; import com.oracle.truffle.r.nodes.attributes.SetAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode; @@ -41,7 +40,7 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; @RBuiltin(name = "storage.mode<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, behavior = PURE) -public abstract class UpdateStorageMode extends RBuiltinNode { +public abstract class UpdateStorageMode extends RBuiltinNode.Arg2 { @Child private TypeFromModeNode typeFromMode = TypeFromModeNodeGen.create(); @Child private TypeofNode typeof; @@ -49,8 +48,6 @@ public abstract class UpdateStorageMode extends RBuiltinNode { @Child private IsFactorNode isFactor; @Child private SetClassAttributeNode setClassAttrNode; - private final BranchProfile errorProfile = BranchProfile.create(); - static { Casts.noCasts(UpdateStorageMode.class); } @@ -61,8 +58,7 @@ public abstract class UpdateStorageMode extends RBuiltinNode { @Cached("create()") SetAttributeNode setAttrNode) { RType mode = typeFromMode.execute(value); if (mode == RType.DefunctReal || mode == RType.DefunctSingle) { - errorProfile.enter(); - throw RError.error(this, RError.Message.USE_DEFUNCT, mode.getName(), mode == RType.DefunctSingle ? "mode<-" : "double"); + throw error(RError.Message.USE_DEFUNCT, mode.getName(), mode == RType.DefunctSingle ? "mode<-" : "double"); } initTypeOfNode(); RType typeX = typeof.execute(x); @@ -71,8 +67,7 @@ public abstract class UpdateStorageMode extends RBuiltinNode { } initFactorNode(); if (isFactor.executeIsFactor(x)) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_STORAGE_MODE_UPDATE); + throw error(RError.Message.INVALID_STORAGE_MODE_UPDATE); } initCastTypeNode(); if (mode != null) { @@ -108,14 +103,13 @@ public abstract class UpdateStorageMode extends RBuiltinNode { return result; } } - errorProfile.enter(); - throw RError.error(this, RError.Message.INVALID_UNNAMED_VALUE); + throw error(RError.Message.INVALID_UNNAMED_VALUE); } private void initCastTypeNode() { if (castTypeNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - castTypeNode = insert(CastTypeNodeGen.create(null, null)); + castTypeNode = insert(CastTypeNodeGen.create()); } } @@ -137,6 +131,6 @@ public abstract class UpdateStorageMode extends RBuiltinNode { @Specialization protected Object update(Object x, Object value) { CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.MUST_BE_NONNULL_STRING, "value"); + throw error(RError.Message.MUST_BE_NONNULL_STRING, "value"); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java index 0211c6ed55c6a46ef7ae1af8074b720bb2ee6427..42273c3a7488f8d3df5887bdaf43b6e3636d76f1 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java @@ -22,6 +22,8 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -36,7 +38,6 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RString; 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; @@ -44,14 +45,15 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "substr<-", kind = INTERNAL, parameterNames = {"x", "start", "stop", "value"}, behavior = PURE) -public abstract class UpdateSubstr extends RBuiltinNode { +public abstract class UpdateSubstr extends RBuiltinNode.Arg4 { private final NACheck na = NACheck.create(); private final BranchProfile everSeenIllegalRange = BranchProfile.create(); static { - Casts.noCasts(UpdateSubstr.class); + Casts casts = new Casts(UpdateSubstr.class); + casts.arg("x").mustBe(nullValue().not().and(stringValue()), RError.Message.REPLACING_IN_NON_CHAR_OBJ).asStringVector(); } private static boolean rangeOk(String x, int start, int stop) { @@ -72,15 +74,18 @@ public abstract class UpdateSubstr extends RBuiltinNode { int actualStop = stop; if (!rangeOk(x, start, stop)) { everSeenIllegalRange.enter(); - if (start > stop || (start <= 0 && stop <= 0) || (start > x.length() && stop > x.length())) { + if (start > x.length()) { return x; } - if (start <= 0) { + if (start < 1) { actualStart = 1; } - if (stop > x.length()) { + if (stop > x.length() || stop < 0) { actualStop = x.length(); } + if (actualStart > actualStop) { + return x; + } } int replacementLength = actualStop - (actualStart - 1); if (replacementLength > value.length()) { @@ -109,34 +114,30 @@ public abstract class UpdateSubstr extends RBuiltinNode { @Specialization(guards = {"!emptyArg(arg)", "!wrongParams(start, stop)"}) @TruffleBoundary protected RStringVector substr(RAbstractStringVector arg, RAbstractIntVector start, RAbstractIntVector stop, RNull value) { - throw RError.error(this, RError.Message.INVALID_UNNAMED_VALUE); + throw error(RError.Message.INVALID_UNNAMED_VALUE); } @SuppressWarnings("unused") - @Specialization(guards = {"!emptyArg(arg)", "!wrongParams(start, stop)", "wrongValue(value)"}) + @Specialization(guards = {"!emptyArg(arg)", "!wrongParams(start, stop)", "!isRAbstractStringVector(value) || value.getLength() == 0"}) protected RStringVector substr(RAbstractStringVector arg, RAbstractIntVector start, RAbstractIntVector stop, RAbstractVector value) { CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.INVALID_UNNAMED_VALUE); + throw error(RError.Message.INVALID_UNNAMED_VALUE); } - @Specialization(guards = {"!emptyArg(arg)", "!wrongParams(start, stop)", "!wrongValue(value)"}) + @Specialization(guards = {"!emptyArg(arg)", "!wrongParams(start, stop)", "value.getLength() > 0"}) @TruffleBoundary protected RStringVector substr(RAbstractStringVector arg, RAbstractIntVector start, RAbstractIntVector stop, RAbstractStringVector value) { - int argLength = arg.getLength(); - String[] res = new String[argLength]; + String[] res = new String[arg.getLength()]; na.enable(arg); na.enable(start); na.enable(stop); int startLength = start.getLength(); int stopLength = stop.getLength(); int valueLength = value.getLength(); - int j; - int k; - int l; - for (int i = 0; i < argLength; i++) { - j = i % startLength; - k = i % stopLength; - l = i % valueLength; + for (int i = 0; i < res.length; i++) { + int j = i % startLength; + int k = i % stopLength; + int l = i % valueLength; res[i] = substr0(arg.getDataAt(i), start.getDataAt(j), stop.getDataAt(k), value.getDataAt(l)); } return RDataFactory.createStringVector(res, na.neverSeenNA()); @@ -149,12 +150,8 @@ public abstract class UpdateSubstr extends RBuiltinNode { protected boolean wrongParams(RAbstractIntVector start, RAbstractIntVector stop) { if (start.getLength() == 0 || stop.getLength() == 0) { - throw RError.error(this, RError.Message.INVALID_ARGUMENTS_NO_QUOTE, "substring"); + throw error(RError.Message.INVALID_ARGUMENTS_NO_QUOTE, "substring"); } return false; } - - protected boolean wrongValue(RAbstractVector value) { - return value.getElementClass() != RString.class || value.getLength() == 0; - } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Utf8ToInt.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Utf8ToInt.java index 50aa92742d8aacee4305eabf32f687c48a09d668..ae78e0c4bef95a99d19a192c2c8aa0699f4f383b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Utf8ToInt.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Utf8ToInt.java @@ -37,12 +37,12 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @RBuiltin(name = "utf8ToInt", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) -public abstract class Utf8ToInt extends RBuiltinNode { +public abstract class Utf8ToInt extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(Utf8ToInt.class); - casts.arg(0, "x").defaultError(RError.SHOW_CALLER, RError.Message.ARG_MUST_BE_CHARACTER_VECTOR_LENGTH_ONE, "x").mustBe(stringValue()).asStringVector().mustBe(notEmpty()).shouldBe(size(1), - RError.SHOW_CALLER, RError.Message.ARG_SHOULD_BE_CHARACTER_VECTOR_LENGTH_ONE).findFirst(); + casts.arg(0, "x").defaultError(RError.Message.ARG_MUST_BE_CHARACTER_VECTOR_LENGTH_ONE, "x").mustBe(stringValue()).asStringVector().mustBe(notEmpty()).shouldBe(size(1), + RError.Message.ARG_SHOULD_BE_CHARACTER_VECTOR_LENGTH_ONE).findFirst(); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java index b8d5a7b81f9b56e90c119e76d0dbeefc6017d74d..56d5d6be3ed430851ed4a990bbc6cab9c95fe72e 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java @@ -23,8 +23,10 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyList; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; @@ -77,7 +79,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; * TODO Set dimnames on result if necessary. */ @RBuiltin(name = "vapply", kind = INTERNAL, parameterNames = {"X", "FUN", "FUN.VALUE", "USE.NAMES"}, splitCaller = true, behavior = COMPLEX) -public abstract class VApply extends RBuiltinNode { +public abstract class VApply extends RBuiltinNode.Arg4 { private final ConditionProfile useNamesProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile dimsProfile = ConditionProfile.createBinaryProfile(); @@ -96,13 +98,10 @@ public abstract class VApply extends RBuiltinNode { static { Casts casts = new Casts(VApply.class); - casts.arg("X").asVector(); - casts.arg("FUN").mustBe(instanceOf(RFunction.class), RError.SHOW_CALLER, RError.Message.APPLY_NON_FUNCTION); - // casts.arg("FUN.VALUE").mapIf(anyValue(), - // chain(asVector(true)).with(mustBe(abstractVectorValue(), RError.SHOW_CALLER, true, - // RError.Message.MUST_BE_VECTOR, "FUN.VALUE")).end()); - casts.arg("FUN.VALUE").defaultError(RError.SHOW_CALLER, RError.Message.MUST_BE_VECTOR, "FUN.VALUE").asVector(true).mustBe(abstractVectorValue()); - casts.arg("USE.NAMES").defaultError(RError.SHOW_CALLER, RError.Message.INVALID_VALUE, "USE.NAMES").mustBe(stringValue().not()).asLogicalVector().findFirst(); + casts.arg("X").mapNull(emptyList()); + casts.arg("FUN").mustBe(instanceOf(RFunction.class), RError.Message.APPLY_NON_FUNCTION); + casts.arg("FUN.VALUE").defaultError(RError.Message.MUST_BE_VECTOR, "FUN.VALUE").mustBe(abstractVectorValue()).asVector(true); + casts.arg("USE.NAMES").defaultError(RError.Message.INVALID_VALUE, "USE.NAMES").mustBe(numericValue()).asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } private Object castComplex(Object operand, boolean preserveAllAttr) { @@ -110,7 +109,7 @@ public abstract class VApply extends RBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); castComplex = insert(CastComplexNodeGen.create(true, preserveAllAttr, preserveAllAttr)); } - return castComplex.execute(operand); + return castComplex.doCast(operand); } private Object castDouble(Object operand, boolean preserveAllAttr) { @@ -118,7 +117,7 @@ public abstract class VApply extends RBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); castDouble = insert(CastDoubleNodeGen.create(true, preserveAllAttr, preserveAllAttr)); } - return castDouble.execute(operand); + return castDouble.doCast(operand); } private Object castInteger(Object operand, boolean preserveAllAttr) { @@ -126,7 +125,7 @@ public abstract class VApply extends RBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); castInteger = insert(CastIntegerNodeGen.create(true, preserveAllAttr, preserveAllAttr)); } - return castInteger.execute(operand); + return castInteger.doCast(operand); } private Object castLogical(Object operand, boolean preserveAllAttr) { @@ -134,7 +133,7 @@ public abstract class VApply extends RBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); castLogical = insert(CastLogicalNodeGen.create(true, preserveAllAttr, preserveAllAttr)); } - return castLogical.execute(operand); + return castLogical.doCast(operand); } private Object castString(Object operand, boolean preserveAllAttr) { @@ -142,17 +141,25 @@ public abstract class VApply extends RBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); castString = insert(CastStringNodeGen.create(true, preserveAllAttr, preserveAllAttr)); } - return castString.execute(operand); + return castString.doCast(operand); } @Specialization - protected Object vapply(VirtualFrame frame, RAbstractVector vec, RFunction fun, RAbstractVector funValue, byte useNames) { - RVector<?> result = delegateToLapply(frame, vec, fun, funValue, useNames); - // set here else it gets overridden by the iterator evaluation - return result; + protected Object vapply(VirtualFrame frame, RAbstractVector vec, RFunction fun, RAbstractVector funValue, boolean useNames) { + return delegateToLapply(frame, vec, fun, funValue, useNames); + } + + @Specialization(guards = "isNotAbstractVector(obj)") + protected Object vapplyNonVector(VirtualFrame frame, Object obj, RFunction fun, RAbstractVector funValue, boolean useNames) { + // wrap the single value into a list and use normal vapply algorithm + return vapply(frame, RDataFactory.createList(new Object[]{obj}), fun, funValue, useNames); + } + + static boolean isNotAbstractVector(Object obj) { + return !(obj instanceof RAbstractVector); } - private RVector<?> delegateToLapply(VirtualFrame frame, RAbstractVector vec, RFunction fun, RAbstractVector funValueVec, byte useNames) { + private RVector<?> delegateToLapply(VirtualFrame frame, RAbstractVector vec, RFunction fun, RAbstractVector funValueVec, boolean useNames) { /* * The implementation is complicated by the existence of scalar length 1 vectors (e.g. * Integer) and concrete length 1 vectors (e.g. RIntVector), as either form can occur in @@ -164,7 +171,7 @@ public abstract class VApply extends RBuiltinNode { RVector<?> vecMat = vec.materialize(); Object[] applyResult = doApply.execute(frame, vecMat, fun); - RVector<?> result = null; + RVector<?> result; boolean applyResultZeroLength = applyResult.length == 0; naCheck.enable(true); @@ -197,7 +204,7 @@ public abstract class VApply extends RBuiltinNode { } // TODO: handle names in case of matrices - if (useNamesProfile.profile(RRuntime.fromLogical(useNames))) { + if (useNamesProfile.profile(useNames)) { RStringVector names = getNamesNode.getNames(vecMat); RStringVector newNames = null; if (names != null) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java index ee217670d4cccdd73e0fec37bba57a8401f459c6..cb883dd4d41421465ce4b4ed4a00c8d28e6e8e35 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java @@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RDataFactory; @RBuiltin(name = "vector", kind = INTERNAL, parameterNames = {"mode", "length"}, behavior = PURE) -public abstract class Vector extends RBuiltinNode { +public abstract class Vector extends RBuiltinNode.Arg2 { private static final String CACHED_MODES_LIMIT = "3"; @@ -46,14 +46,14 @@ public abstract class Vector extends RBuiltinNode { static { Casts casts = new Casts(Vector.class); - casts.arg("mode").defaultError(RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "mode").asStringVector().mustBe(singleElement()).findFirst(); - casts.arg("length").defaultError(RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "length").asIntegerVector().mustBe(singleElement()).findFirst(); + casts.arg("mode").defaultError(RError.Message.INVALID_ARGUMENT, "mode").asStringVector().mustBe(singleElement()).findFirst(); + casts.arg("length").defaultError(RError.Message.INVALID_ARGUMENT, "length").asIntegerVector().mustBe(singleElement()).findFirst(); } protected RType modeToType(String mode) { RType type = typeFromMode.execute(mode); if (type != RType.PairList && !type.isVector()) { - throw RError.error(this, RError.Message.CANNOT_MAKE_VECTOR_OF_MODE, mode); + throw error(RError.Message.CANNOT_MAKE_VECTOR_OF_MODE, mode); } return type; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Warning.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Warning.java index 164019046ff4edb35b945d0888af84da8adf7d26..fa420e5b0a7d5d79b82ac2805d2fc79eaf49621c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Warning.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Warning.java @@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.RErrorHandling; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "warning", visibility = OFF, kind = INTERNAL, parameterNames = {"call", "immediate", "nobreaks", "message"}, behavior = COMPLEX) -public abstract class Warning extends RBuiltinNode { +public abstract class Warning extends RBuiltinNode.Arg4 { static { Casts casts = new Casts(Warning.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java index 1a7797de13201002e0ffbcd5197989a1491c5b01..25a8810a9e29a3e588cd61e397c78e0b43314d93 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java @@ -51,7 +51,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; public class WhichFunctions { @RBuiltin(name = "which", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE) - public abstract static class Which extends RBuiltinNode { + public abstract static class Which extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(Which.class); @@ -102,7 +102,7 @@ public class WhichFunctions { } } - public abstract static class WhichMinMax extends RBuiltinNode { + public abstract static class WhichMinMax extends RBuiltinNode.Arg1 { private final boolean isMax; @@ -110,9 +110,9 @@ public class WhichFunctions { this.isMax = isMax; } - protected static Casts createCasts(Class<? extends WhichMinMax> extCls) { + static Casts createCasts(Class<? extends WhichMinMax> extCls) { Casts casts = new Casts(extCls); - casts.arg(0, "x").asDoubleVector(true, false, false); + casts.arg(0, "x").mustNotBeMissing().asDoubleVector(true, false, false); return casts; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java index fa52a36dfcb76e8a3c494bfadc59bedee2360544..6f2f5ce21b1c2893f0942a4e181f72339a943ff2 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java @@ -33,7 +33,6 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.PromiseHelperNode; import com.oracle.truffle.r.nodes.function.visibility.GetVisibilityNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; -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.builtins.RBuiltin; @@ -57,8 +56,7 @@ final class WithVisibleSpecial extends RNode { public Object execute(VirtualFrame frame) { Object value = delegate.visibleExecute(frame); if (value == RMissing.instance) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, Message.ARGUMENT_MISSING, "x"); + throw error(Message.ARGUMENT_MISSING, "x"); } return RDataFactory.createList(new Object[]{value, RRuntime.asLogical(visibility.execute(frame))}, WithVisible.LISTNAMES); } @@ -69,7 +67,7 @@ final class WithVisibleSpecial extends RNode { // gets the wrong result. I believe that the only way to handle it as a .Internal would be to // set noEvalArgs and evaluate the argument here and set the visibility explicitly. @RBuiltin(name = "withVisible", kind = PRIMITIVE, parameterNames = "x", behavior = COMPLEX, nonEvalArgs = {0}) -public abstract class WithVisible extends RBuiltinNode { +public abstract class WithVisible extends RBuiltinNode.Arg1 { static final RStringVector LISTNAMES = (RStringVector) RDataFactory.createStringVector(new String[]{"value", "visible"}, RDataFactory.COMPLETE_VECTOR).makeSharedPermanent(); @@ -87,7 +85,7 @@ public abstract class WithVisible extends RBuiltinNode { Object value = promiseHelper.evaluate(frame, x); if (value == RMissing.instance) { CompilerDirectives.transferToInterpreter(); - throw RError.error(this, Message.ARGUMENT_MISSING, "x"); + throw error(Message.ARGUMENT_MISSING, "x"); } return RDataFactory.createList(new Object[]{value, RRuntime.asLogical(visibility.execute(frame))}, LISTNAMES); } @@ -98,7 +96,6 @@ public abstract class WithVisible extends RBuiltinNode { @Specialization protected RList withVisible(@SuppressWarnings("unused") RMissing x) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, Message.ARGUMENT_MISSING, "x"); + throw error(Message.ARGUMENT_MISSING, "x"); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Xtfrm.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Xtfrm.java index 7d2c7fdfc68f94376451a5b07c2614759a4eb999..abac7f57b85b22c01cf560bddb9d11ab29e4fe4f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Xtfrm.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Xtfrm.java @@ -41,7 +41,7 @@ import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.env.REnvironment; @RBuiltin(name = "xtfrm", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = COMPLEX) -public abstract class Xtfrm extends RBuiltinNode { +public abstract class Xtfrm extends RBuiltinNode.Arg1 { @Child private GetFunctions.Get getNode; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/AssignFastPath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/AssignFastPath.java index 377add37242b337a7190bae705e569edbc374d29..ae1586c95a16eb5e756455022ee01516b1fa0638 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/AssignFastPath.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/AssignFastPath.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 @@ -40,25 +40,25 @@ public abstract class AssignFastPath extends RFastPathNode { @Specialization @SuppressWarnings("unused") protected Object assign(VirtualFrame frame, RAbstractStringVector x, Object value, RMissing pos, REnvironment envir, byte inherits, Object immediate) { - return assign.executeBuiltin(frame, x, value, envir, inherits); + return assign.execute(frame, x, value, envir, inherits); } @Specialization @SuppressWarnings("unused") protected Object assign(VirtualFrame frame, RAbstractStringVector x, Object value, RMissing pos, REnvironment envir, RMissing inherits, Object immediate) { - return assign.executeBuiltin(frame, x, value, envir, RRuntime.LOGICAL_FALSE); + return assign.execute(frame, x, value, envir, RRuntime.LOGICAL_FALSE); } @Specialization @SuppressWarnings("unused") protected Object assign(VirtualFrame frame, RAbstractStringVector x, Object value, REnvironment pos, RMissing envir, byte inherits, Object immediate) { - return assign.executeBuiltin(frame, x, value, pos, inherits); + return assign.execute(frame, x, value, pos, inherits); } @Specialization @SuppressWarnings("unused") protected Object assign(VirtualFrame frame, RAbstractStringVector x, Object value, REnvironment pos, RMissing envir, RMissing inherits, Object immediate) { - return assign.executeBuiltin(frame, x, value, pos, RRuntime.LOGICAL_FALSE); + return assign.execute(frame, x, value, pos, RRuntime.LOGICAL_FALSE); } @Fallback diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IntersectFastPath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IntersectFastPath.java index 0089dad0f3bf6b5dc35c88ee84c4cc4b129677b9..5d746b49b97ac9dce9232dc5b695e56cf22ad10e 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IntersectFastPath.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IntersectFastPath.java @@ -24,10 +24,13 @@ package com.oracle.truffle.r.nodes.builtin.base.fastpaths; import java.util.Arrays; +import com.oracle.truffle.api.CompilerDirectives; 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.nodes.Node; +import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @@ -40,76 +43,157 @@ public abstract class IntersectFastPath extends RFastPathNode { private static final int[] EMPTY_INT_ARRAY = new int[0]; - @Specialization(limit = "TYPE_LIMIT", guards = {"x.getLength() > 0", "y.getLength() > 0", "x.getClass() == xClass", "y.getClass() == yClass"}) - protected RAbstractIntVector intersect(RAbstractIntVector x, RAbstractIntVector y, - @Cached("x.getClass()") Class<? extends RAbstractIntVector> xClass, - @Cached("y.getClass()") Class<? extends RAbstractIntVector> yClass, - @Cached("createBinaryProfile()") ConditionProfile isXSortedProfile, - @Cached("createBinaryProfile()") ConditionProfile isYSortedProfile, - @Cached("createBinaryProfile()") ConditionProfile resultLengthMatchProfile) { - // apply the type profiles: - RAbstractIntVector profiledX = xClass.cast(x); - RAbstractIntVector profiledY = yClass.cast(y); + protected static final class IntersectSortedNode extends Node { - int xLength = profiledX.getLength(); - int yLength = profiledY.getLength(); - RBaseNode.reportWork(this, xLength + yLength); + private final boolean isSorted; - int count = 0; - int[] result = EMPTY_INT_ARRAY; - int maxResultLength = Math.min(xLength, yLength); - if (isXSortedProfile.profile(isSorted(profiledX))) { - RAbstractIntVector tempY; - if (isYSortedProfile.profile(isSorted(profiledY))) { - tempY = profiledY; - } else { - int[] temp = new int[yLength]; - for (int i = 0; i < yLength; i++) { - temp[i] = profiledY.getDataAt(i); - } - sort(temp); - tempY = RDataFactory.createIntVector(temp, profiledY.isComplete()); - } + private final ConditionProfile resizeProfile = ConditionProfile.createCountingProfile(); + private final ConditionProfile valueEqualsProfile = ConditionProfile.createCountingProfile(); + private final ConditionProfile valueSmallerProfile = ConditionProfile.createCountingProfile(); + private final ConditionProfile exit1Profile = ConditionProfile.createCountingProfile(); + private final ConditionProfile exit2Profile = ConditionProfile.createCountingProfile(); + private final ConditionProfile exit3Profile = ConditionProfile.createCountingProfile(); + private final ConditionProfile exit4Profile = ConditionProfile.createCountingProfile(); + private final ConditionProfile exit5Profile = ConditionProfile.createCountingProfile(); + private final ConditionProfile exit6Profile = ConditionProfile.createCountingProfile(); + private final ConditionProfile resultLengthMatchProfile = ConditionProfile.createBinaryProfile(); + + protected IntersectSortedNode(boolean isSorted) { + this.isSorted = isSorted; + } + + @Override + public NodeCost getCost() { + return NodeCost.NONE; + } + + private int[] execute(RAbstractIntVector x, int xLength, int yLength, RAbstractIntVector y) { + int[] result = EMPTY_INT_ARRAY; + int maxResultLength = Math.min(xLength, yLength); + int count = 0; int xPos = 0; int yPos = 0; - int xValue = profiledX.getDataAt(xPos); - int yValue = tempY.getDataAt(yPos); + int xValue = x.getDataAt(xPos); + int yValue = y.getDataAt(yPos); while (true) { - if (xValue == yValue) { - if (count >= result.length) { + if (valueEqualsProfile.profile(xValue == yValue)) { + if (resizeProfile.profile(count >= result.length)) { result = Arrays.copyOf(result, Math.min(maxResultLength, Math.max(result.length * 2, 8))); } result[count++] = xValue; // advance over similar entries while (true) { - if (xPos >= xLength - 1) { + if (exit1Profile.profile(xPos >= xLength - 1)) { break; } - int nextValue = profiledX.getDataAt(xPos + 1); - if (xValue != nextValue) { + int nextValue = x.getDataAt(xPos + 1); + if (exit2Profile.profile(xValue != nextValue)) { break; } xPos++; xValue = nextValue; } - if (++xPos >= xLength || ++yPos >= yLength) { + if (exit3Profile.profile(++xPos >= xLength) || exit4Profile.profile(++yPos >= yLength)) { break; } - xValue = profiledX.getDataAt(xPos); - yValue = tempY.getDataAt(yPos); - } else if (xValue < yValue) { - if (++xPos >= xLength) { + xValue = getNextValue(x, xPos, xValue); + yValue = getNextValue(y, yPos, yValue); + } else if (valueSmallerProfile.profile(xValue < yValue)) { + if (exit5Profile.profile(++xPos >= xLength)) { break; } - xValue = profiledX.getDataAt(xPos); + xValue = getNextValue(x, xPos, xValue); } else { - if (++yPos >= yLength) { + if (exit6Profile.profile(++yPos >= yLength)) { break; } - yValue = tempY.getDataAt(yPos); + yValue = getNextValue(y, yPos, yValue); + } + } + if (!isSorted) { + // check remaining array entries + while (++xPos < xLength) { + xValue = getNextValue(x, xPos, xValue); } + while (++yPos < yLength) { + yValue = getNextValue(y, yPos, yValue); + } + } + return resultLengthMatchProfile.profile(count == result.length) ? result : Arrays.copyOf(result, count); + } + + private int getNextValue(RAbstractIntVector vector, int pos, int oldValue) { + int newValue = vector.getDataAt(pos); + if (!isSorted && newValue < oldValue) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + throw new IllegalArgumentException(); + } + return newValue; + } + } + + protected static int length(RAbstractIntVector v, Class<? extends RAbstractIntVector> clazz) { + return clazz.cast(v).getLength(); + } + + protected static IntersectSortedNode createMaybeSorted() { + return new IntersectSortedNode(false); + } + + @Specialization(limit = "TYPE_LIMIT", guards = {"x.getClass() == xClass", "y.getClass() == yClass", "length(x, xClass) > 0", "length(y, yClass) > 0"}, rewriteOn = IllegalArgumentException.class) + protected RAbstractIntVector intersectMaybeSorted(RAbstractIntVector x, RAbstractIntVector y, + @Cached("x.getClass()") Class<? extends RAbstractIntVector> xClass, + @Cached("y.getClass()") Class<? extends RAbstractIntVector> yClass, + @Cached("createMaybeSorted()") IntersectSortedNode intersect) { + // apply the type profiles: + RAbstractIntVector profiledX = xClass.cast(x); + RAbstractIntVector profiledY = yClass.cast(y); + + int xLength = profiledX.getLength(); + int yLength = profiledY.getLength(); + RBaseNode.reportWork(this, xLength + yLength); + + int[] result = intersect.execute(profiledX, xLength, yLength, profiledY); + return RDataFactory.createIntVector(result, profiledX.isComplete() | profiledY.isComplete()); + } + + protected static IntersectSortedNode createSorted() { + return new IntersectSortedNode(true); + } + + @Specialization(limit = "TYPE_LIMIT", guards = {"x.getClass() == xClass", "y.getClass() == yClass", "length(x, xClass) > 0", "length(y, yClass) > 0"}) + protected RAbstractIntVector intersect(RAbstractIntVector x, RAbstractIntVector y, + @Cached("x.getClass()") Class<? extends RAbstractIntVector> xClass, + @Cached("y.getClass()") Class<? extends RAbstractIntVector> yClass, + @Cached("createBinaryProfile()") ConditionProfile isXSortedProfile, + @Cached("createBinaryProfile()") ConditionProfile isYSortedProfile, + @Cached("createBinaryProfile()") ConditionProfile resultLengthMatchProfile, + @Cached("createSorted()") IntersectSortedNode intersect) { + // apply the type profiles: + RAbstractIntVector profiledX = xClass.cast(x); + RAbstractIntVector profiledY = yClass.cast(y); + + int xLength = profiledX.getLength(); + int yLength = profiledY.getLength(); + RBaseNode.reportWork(this, xLength + yLength); + + int[] result; + if (isXSortedProfile.profile(isSorted(profiledX))) { + RAbstractIntVector tempY; + if (isYSortedProfile.profile(isSorted(profiledY))) { + tempY = profiledY; + } else { + int[] temp = new int[yLength]; + for (int i = 0; i < yLength; i++) { + temp[i] = profiledY.getDataAt(i); + } + sort(temp); + tempY = RDataFactory.createIntVector(temp, profiledY.isComplete()); } + result = intersect.execute(profiledX, xLength, yLength, tempY); } else { + result = EMPTY_INT_ARRAY; + int maxResultLength = Math.min(xLength, yLength); int[] temp = new int[yLength]; boolean[] used = new boolean[yLength]; for (int i = 0; i < yLength; i++) { @@ -117,6 +201,7 @@ public abstract class IntersectFastPath extends RFastPathNode { } sort(temp); + int count = 0; for (int i = 0; i < xLength; i++) { int value = profiledX.getDataAt(i); int pos = Arrays.binarySearch(temp, value); @@ -128,8 +213,9 @@ public abstract class IntersectFastPath extends RFastPathNode { result[count++] = value; } } + result = resultLengthMatchProfile.profile(count == result.length) ? result : Arrays.copyOf(result, count); } - return RDataFactory.createIntVector(resultLengthMatchProfile.profile(count == result.length) ? result : Arrays.copyOf(result, count), profiledX.isComplete() | profiledY.isComplete()); + return RDataFactory.createIntVector(result, profiledX.isComplete() | profiledY.isComplete()); } private static boolean isSorted(RAbstractIntVector vector) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IsElementFastPath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IsElementFastPath.java index 3239623be3b4baca0f6f05e25b6d7f349f156f3e..c211bb753ea774dc4e87c6f5e7e69554bbd9067b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IsElementFastPath.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IsElementFastPath.java @@ -37,10 +37,14 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; public abstract class IsElementFastPath extends RFastPathNode { - @Specialization(guards = "el.getLength() == 1") - protected Byte iselementOne(RAbstractStringVector el, RAbstractStringVector set, + @Specialization(guards = {"elIn.getLength() == 1", "elIn.getClass() == elClass", "setIn.getClass() == setClass"}) + protected Byte iselementOneCachedString(RAbstractStringVector elIn, RAbstractStringVector setIn, + @Cached("elIn.getClass()") Class<? extends RAbstractStringVector> elClass, + @Cached("setIn.getClass()") Class<? extends RAbstractStringVector> setClass, @Cached("create()") BranchProfile trueProfile, @Cached("create()") BranchProfile falseProfile) { + RAbstractStringVector el = elClass.cast(elIn); + RAbstractStringVector set = setClass.cast(setIn); String element = el.getDataAt(0); int length = set.getLength(); for (int i = 0; i < length; i++) { @@ -53,6 +57,13 @@ public abstract class IsElementFastPath extends RFastPathNode { return RRuntime.LOGICAL_FALSE; } + @Specialization(replaces = "iselementOneCachedString") + protected Byte iselementOne(RAbstractStringVector elIn, RAbstractStringVector setIn, + @Cached("create()") BranchProfile trueProfile, + @Cached("create()") BranchProfile falseProfile) { + return iselementOneCachedString(elIn, setIn, RAbstractStringVector.class, RAbstractStringVector.class, trueProfile, falseProfile); + } + @Specialization protected Byte iselementOne(double el, double set) { return RRuntime.asLogical(el == set); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/MatrixFastPath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/MatrixFastPath.java index 056af9a7e51954303bca4e6b688660ec1ddcfa10..1be6fc9e6c8e5123c859945c0eaf5ca457b8a672 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/MatrixFastPath.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/MatrixFastPath.java @@ -26,6 +26,7 @@ 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.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.builtin.base.Matrix; import com.oracle.truffle.r.nodes.builtin.base.MatrixNodeGen; import com.oracle.truffle.r.nodes.unary.CastIntegerNode; @@ -55,13 +56,14 @@ public abstract class MatrixFastPath extends RFastPathNode { @Cached("createBinaryProfile()") ConditionProfile rowMissingProfile, @Cached("createBinaryProfile()") ConditionProfile colMissingProfile, @Cached("createBinaryProfile()") ConditionProfile dimMissingProfile, - @Cached("createMatrix()") Matrix matrix) { + @Cached("createMatrix()") Matrix matrix, + @Cached("createClassProfile()") ValueProfile classProfile) { boolean rowMissing = rowMissingProfile.profile(nrow == RMissing.instance); boolean colMissing = colMissingProfile.profile(ncol == RMissing.instance); - int row = rowMissing ? 1 : firstRow.executeInt(castRow.execute(nrow)); - int col = colMissing ? 1 : firstCol.executeInt(castCol.execute(ncol)); + int row = rowMissing ? 1 : firstRow.executeInt(castRow.doCast(nrow)); + int col = colMissing ? 1 : firstCol.executeInt(castCol.doCast(ncol)); Object dim = dimMissingProfile.profile(dimnames == RMissing.instance) ? RNull.instance : dimnames; - return matrix.execute(data, row, col, false, dim, rowMissing, colMissing); + return matrix.execute(classProfile.profile(data), row, col, false, dim, rowMissing, colMissing); } @Fallback diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CairoProps.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CairoProps.java index 4f9d28cfb20ff21248fc873b73113f5b7a46baf5..f0dcad3ee3ff19a5871bb5a7d43d16d0e5b0bd79 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CairoProps.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CairoProps.java @@ -11,6 +11,10 @@ */ package com.oracle.truffle.r.nodes.builtin.base.foreign; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyIntegerVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; + import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.runtime.RRuntime; @@ -20,7 +24,7 @@ public abstract class CairoProps extends RExternalBuiltinNode.Arg1 { static { Casts casts = new Casts(CairoProps.class); - casts.arg(0).asIntegerVector(); + casts.arg(0).returnIf(nullValue().or(missingValue()), emptyIntegerVector()).asIntegerVector(); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java index 1eae28232995f9b72a0ec43819f80db65a246506..a498b2d75c9388fa293795c0cf030f46688d9b76 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java @@ -15,18 +15,14 @@ import static com.oracle.truffle.r.runtime.RVisibility.CUSTOM; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; 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.frame.VirtualFrame; -import com.oracle.truffle.api.profiles.BranchProfile; -import com.oracle.truffle.r.library.grDevices.DevicesCCalls; -import com.oracle.truffle.r.library.graphics.GraphicsCCalls; -import com.oracle.truffle.r.library.graphics.GraphicsCCalls.C_Par; -import com.oracle.truffle.r.library.graphics.GraphicsCCalls.C_PlotXY; -import com.oracle.truffle.r.library.grid.GridFunctionsFactory.InitGridNodeGen; -import com.oracle.truffle.r.library.grid.GridFunctionsFactory.ValidUnitsNodeGen; +import com.oracle.truffle.r.library.fastrGrid.FastRGridExternalLookup; import com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_M_setPrimitiveMethodsNodeGen; import com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_externalPtrPrototypeObjectNodeGen; import com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_getClassFromCacheNodeGen; @@ -56,12 +52,14 @@ import com.oracle.truffle.r.library.stats.SplineFunctionsFactory.SplineCoefNodeG import com.oracle.truffle.r.library.stats.SplineFunctionsFactory.SplineEvalNodeGen; import com.oracle.truffle.r.library.stats.StatsFunctionsNodes; import com.oracle.truffle.r.library.stats.WilcoxFreeNode; +import com.oracle.truffle.r.library.stats.deriv.D; +import com.oracle.truffle.r.library.stats.deriv.Deriv; import com.oracle.truffle.r.library.tools.C_ParseRdNodeGen; import com.oracle.truffle.r.library.tools.DirChmodNodeGen; import com.oracle.truffle.r.library.tools.Rmd5NodeGen; import com.oracle.truffle.r.library.tools.ToolsTextFactory.CodeFilesAppendNodeGen; import com.oracle.truffle.r.library.tools.ToolsTextFactory.DoTabExpandNodeGen; -import com.oracle.truffle.r.library.utils.CountFields; +import com.oracle.truffle.r.library.utils.CountFieldsNodeGen; import com.oracle.truffle.r.library.utils.Crc64NodeGen; import com.oracle.truffle.r.library.utils.DownloadNodeGen; import com.oracle.truffle.r.library.utils.MenuNodeGen; @@ -76,6 +74,7 @@ import com.oracle.truffle.r.nodes.objects.NewObjectNodeGen; import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalCode; +import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; @@ -201,10 +200,6 @@ public class CallAndExternalFunctions { return list; } - abstract static class CallRFFIAdapter extends LookupAdapter { - @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode(); - } - /** * Handles the generic case, but also many special case functions that are called from the * default packages. @@ -222,9 +217,9 @@ public class CallAndExternalFunctions { * could be invoked by a string but experimentally that situation has never been encountered. */ @RBuiltin(name = ".Call", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX) - public abstract static class DotCall extends CallRFFIAdapter { + public abstract static class DotCall extends LookupAdapter { - private final BranchProfile errorProfile = BranchProfile.create(); + @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode(); static { Casts.noCasts(DotCall.class); @@ -237,8 +232,14 @@ public class CallAndExternalFunctions { @Override @TruffleBoundary - protected RExternalBuiltinNode lookupBuiltin(RList symbol) { + public RExternalBuiltinNode lookupBuiltin(RList symbol) { String name = lookupName(symbol); + if (FastROptions.UseInternalGridGraphics.getBooleanValue() && name != null) { + RExternalBuiltinNode gridExternal = FastRGridExternalLookup.lookupDotCall(name); + if (gridExternal != null) { + return gridExternal; + } + } switch (name) { // methods case "R_initMethodDispatch": @@ -628,24 +629,6 @@ public class CallAndExternalFunctions { // parallel case "mc_is_child": return MCIsChildNodeGen.create(); - default: - return FastROptions.UseInternalGraphics.getBooleanValue() ? lookupGraphicsBuiltin(name) : null; - } - } - - private static RExternalBuiltinNode lookupGraphicsBuiltin(String name) { - switch (name) { - // grDevices - case "cairoProps": - return CairoPropsNodeGen.create(); - case "makeQuartzDefault": - return new MakeQuartzDefault(); - - // grid - case "L_initGrid": - return InitGridNodeGen.create(); - case "L_validUnits": - return ValidUnitsNodeGen.create(); default: return null; } @@ -655,7 +638,7 @@ public class CallAndExternalFunctions { * {@code .NAME = NativeSymbolInfo} implemented as a builtin. */ @SuppressWarnings("unused") - @Specialization(limit = "1", guards = {"cached == symbol", "builtin != null"}) + @Specialization(limit = "99", guards = {"cached == symbol", "builtin != null"}) protected Object doExternal(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, Object packageName, @Cached("symbol") RList cached, @Cached("lookupBuiltin(symbol)") RExternalBuiltinNode builtin) { @@ -667,10 +650,11 @@ public class CallAndExternalFunctions { * package) */ @SuppressWarnings("unused") - @Specialization(limit = "2", guards = {"cached == symbol"}) + @Specialization(limit = "2", guards = {"cached == symbol", "builtin == null"}) protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, Object packageName, @Cached("symbol") RList cached, - @Cached("extractSymbolInfo(frame, symbol)") NativeCallInfo nativeCallInfo) { + @Cached("lookupBuiltin(symbol)") RExternalBuiltinNode builtin, + @Cached("extractSymbolInfo.execute(frame, symbol)") NativeCallInfo nativeCallInfo) { return callRFFINode.execute(nativeCallInfo, args.getArguments()); } @@ -679,9 +663,13 @@ public class CallAndExternalFunctions { * such cases there is this generic version. */ @SuppressWarnings("unused") - @Specialization(replaces = "callNamedFunction") + @Specialization(replaces = {"callNamedFunction", "doExternal"}) protected Object callNamedFunctionGeneric(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, Object packageName) { - NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol); + RExternalBuiltinNode builtin = lookupBuiltin(symbol); + if (builtin != null) { + throw RInternalError.shouldNotReachHere("Cache for .Calls with FastR reimplementation (lookupBuiltin(...) != null) exceeded the limit"); + } + NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(frame, symbol); return callRFFINode.execute(nativeCallInfo, args.getArguments()); } @@ -705,8 +693,7 @@ public class CallAndExternalFunctions { @Cached("create()") DLL.RFindSymbolNode findSymbolNode) { DLL.SymbolHandle func = findSymbolNode.execute(symbol, packageName, rns); if (func == DLL.SYMBOL_NOT_FOUND) { - errorProfile.enter(); - throw RError.error(this, RError.Message.SYMBOL_NOT_IN_TABLE, symbol, "Call", packageName); + throw error(RError.Message.SYMBOL_NOT_IN_TABLE, symbol, "Call", packageName); } return callRFFINode.execute(new NativeCallInfo(symbol, func, rns.getDllInfo()), args.getArguments()); } @@ -714,7 +701,7 @@ public class CallAndExternalFunctions { @SuppressWarnings("unused") @Fallback protected Object dotCallFallback(Object symbol, Object args, Object packageName) { - throw fallback(symbol); + throw fallback(this, symbol); } } @@ -723,9 +710,9 @@ public class CallAndExternalFunctions { * {@link DotCall}. */ @RBuiltin(name = ".External", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX) - public abstract static class DotExternal extends CallRFFIAdapter { + public abstract static class DotExternal extends LookupAdapter { - private final BranchProfile errorProfile = BranchProfile.create(); + @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode(); static { Casts.noCasts(DotExternal.class); @@ -733,24 +720,25 @@ public class CallAndExternalFunctions { @Override @TruffleBoundary - protected RExternalBuiltinNode lookupBuiltin(RList f) { + public RExternalBuiltinNode lookupBuiltin(RList f) { String name = lookupName(f); - if (FastROptions.UseInternalGraphics.getBooleanValue()) { - switch (name) { - case "PDF": - return new DevicesCCalls.C_PDF(); - case "devoff": - return DevicesCCalls.C_DevOff.create(); - case "devcur": - return new DevicesCCalls.C_DevCur(); + if (FastROptions.UseInternalGridGraphics.getBooleanValue()) { + RExternalBuiltinNode gridExternal = FastRGridExternalLookup.lookupDotExternal(name); + if (gridExternal != null) { + return gridExternal; } } switch (name) { case "compcases": return new CompleteCases(); + // stats + case "doD": + return D.create(); + case "deriv": + return Deriv.create(); // utils case "countfields": - return new CountFields(); + return CountFieldsNodeGen.create(); case "readtablehead": return ReadTableHeadNodeGen.create(); case "download": @@ -792,7 +780,7 @@ public class CallAndExternalFunctions { @Specialization(limit = "1", guards = {"cached == symbol"}) protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, Object packageName, @Cached("symbol") RList cached, - @Cached("extractSymbolInfo(frame, symbol)") NativeCallInfo nativeCallInfo) { + @Cached("extractSymbolInfo.execute(frame, symbol)") NativeCallInfo nativeCallInfo) { Object list = encodeArgumentPairList(args, nativeCallInfo.name); return callRFFINode.execute(nativeCallInfo, new Object[]{list}); } @@ -810,8 +798,7 @@ public class CallAndExternalFunctions { @Cached("create()") DLL.RFindSymbolNode findSymbolNode) { DLL.SymbolHandle func = findSymbolNode.execute(symbol, packageName, rns); if (func == DLL.SYMBOL_NOT_FOUND) { - errorProfile.enter(); - throw RError.error(this, RError.Message.SYMBOL_NOT_IN_TABLE, symbol, "External", packageName); + throw error(RError.Message.SYMBOL_NOT_IN_TABLE, symbol, "External", packageName); } Object list = encodeArgumentPairList(args, symbol); return callRFFINode.execute(new NativeCallInfo(symbol, func, rns.getDllInfo()), new Object[]{list}); @@ -819,32 +806,48 @@ public class CallAndExternalFunctions { @Fallback protected Object fallback(Object f, @SuppressWarnings("unused") Object args, @SuppressWarnings("unused") Object packageName) { - throw fallback(f); + throw fallback(this, f); } } @RBuiltin(name = ".External2", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX) - public abstract static class DotExternal2 extends CallRFFIAdapter { + public abstract static class DotExternal2 extends LookupAdapter { private static final Object CALL = "call"; - private static final Object OP = "op"; private static final Object RHO = "rho"; + /** + * This argument for the native function should be SPECIALSXP reprenting the .External2 + * builtin. In GnuR SPECIALSXP is index into the table of builtins. External2 and External + * are in fact one native function with two entries in this table, the "op" argument is used + * to determine whether the call was made to .External or .External2. The actual code of the + * native function that is eventually invoked will always get SPECIALSXP reprenting the + * .External2, becuase functions exported as .External do not take the "op" argument. + */ + @CompilationFinal private static Object op = null; + + @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode(); static { Casts.noCasts(DotExternal2.class); } - private final BranchProfile errorProfile = BranchProfile.create(); + private static Object getOp() { + if (op == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + op = RContext.lookupBuiltin(".External2"); + } + return op; + } @Override @TruffleBoundary - protected RExternalBuiltinNode lookupBuiltin(RList symbol) { - if (FastROptions.UseInternalGraphics.getBooleanValue()) { - switch (lookupName(symbol)) { - case "C_par": - return new C_Par(); + public RExternalBuiltinNode lookupBuiltin(RList symbol) { + String name = lookupName(symbol); + if (FastROptions.UseInternalGridGraphics.getBooleanValue()) { + RExternalBuiltinNode gridExternal = FastRGridExternalLookup.lookupDotExternal2(name); + if (gridExternal != null) { + return gridExternal; } } - String name = lookupName(symbol); switch (name) { // tools case "writetable": @@ -873,10 +876,9 @@ public class CallAndExternalFunctions { @Specialization(limit = "1", guards = {"cached == symbol"}) protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, Object packageName, @Cached("symbol") RList cached, - @Cached("extractSymbolInfo(frame, symbol)") NativeCallInfo nativeCallInfo) { + @Cached("extractSymbolInfo.execute(frame, symbol)") NativeCallInfo nativeCallInfo) { Object list = encodeArgumentPairList(args, nativeCallInfo.name); - // TODO: provide proper values for the CALL, OP and RHO parameters - return callRFFINode.execute(nativeCallInfo, new Object[]{CALL, OP, list, RHO}); + return callRFFINode.execute(nativeCallInfo, new Object[]{CALL, getOp(), list, RHO}); } @Specialization @@ -892,24 +894,22 @@ public class CallAndExternalFunctions { @Cached("create()") DLL.RFindSymbolNode findSymbolNode) { DLL.SymbolHandle func = findSymbolNode.execute(symbol, packageName, rns); if (func == DLL.SYMBOL_NOT_FOUND) { - errorProfile.enter(); - throw RError.error(this, RError.Message.SYMBOL_NOT_IN_TABLE, symbol, "External2", packageName); + throw error(RError.Message.SYMBOL_NOT_IN_TABLE, symbol, "External2", packageName); } Object list = encodeArgumentPairList(args, symbol); - // TODO: provide proper values for the CALL, OP and RHO parameters - return callRFFINode.execute(new NativeCallInfo(symbol, func, rns.getDllInfo()), new Object[]{CALL, OP, list, RHO}); + return callRFFINode.execute(new NativeCallInfo(symbol, func, rns.getDllInfo()), new Object[]{CALL, getOp(), list, RHO}); } @Fallback protected Object fallback(Object f, @SuppressWarnings("unused") Object args, @SuppressWarnings("unused") Object packageName) { - throw fallback(f); + throw fallback(this, f); } } @RBuiltin(name = ".External.graphics", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX) - public abstract static class DotExternalGraphics extends CallRFFIAdapter { + public abstract static class DotExternalGraphics extends LookupAdapter { - private final BranchProfile errorProfile = BranchProfile.create(); + @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode(); static { Casts.noCasts(DotExternalGraphics.class); @@ -917,15 +917,7 @@ public class CallAndExternalFunctions { @Override @TruffleBoundary - protected RExternalBuiltinNode lookupBuiltin(RList f) { - if (FastROptions.UseInternalGraphics.getBooleanValue()) { - switch (lookupName(f)) { - case "C_mtext": - return new GraphicsCCalls.C_mtext(); - case "C_plotXY": - return new C_PlotXY(); - } - } + public RExternalBuiltinNode lookupBuiltin(RList f) { return null; } @@ -939,7 +931,7 @@ public class CallAndExternalFunctions { @Specialization protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") Object packageName) { - NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol); + NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(frame, symbol); Object list = encodeArgumentPairList(args, nativeCallInfo.name); return callRFFINode.execute(nativeCallInfo, new Object[]{list}); } @@ -956,8 +948,7 @@ public class CallAndExternalFunctions { DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.External, null, null); DLL.SymbolHandle func = findSymbolNode.execute(name, packageName, rns); if (func == DLL.SYMBOL_NOT_FOUND) { - errorProfile.enter(); - throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, name); + throw error(RError.Message.C_SYMBOL_NOT_IN_TABLE, name); } Object list = encodeArgumentPairList(args, name); return callRFFINode.execute(new NativeCallInfo(name, func, rns.getDllInfo()), new Object[]{list}); @@ -965,14 +956,14 @@ public class CallAndExternalFunctions { @Fallback protected Object fallback(Object f, @SuppressWarnings("unused") Object args, @SuppressWarnings("unused") Object packageName) { - throw fallback(f); + throw fallback(this, f); } } @RBuiltin(name = ".Call.graphics", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX) - public abstract static class DotCallGraphics extends CallRFFIAdapter { + public abstract static class DotCallGraphics extends LookupAdapter { - private final BranchProfile errorProfile = BranchProfile.create(); + @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode(); static { Casts.noCasts(DotCallGraphics.class); @@ -985,7 +976,7 @@ public class CallAndExternalFunctions { @Override @TruffleBoundary - protected RExternalBuiltinNode lookupBuiltin(RList f) { + public RExternalBuiltinNode lookupBuiltin(RList f) { switch (lookupName(f)) { default: return null; @@ -1002,7 +993,7 @@ public class CallAndExternalFunctions { @Specialization protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") Object packageName) { - NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol); + NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(frame, symbol); return callRFFINode.execute(nativeCallInfo, args.getArguments()); } @@ -1019,15 +1010,14 @@ public class CallAndExternalFunctions { DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.Call, null, null); DLL.SymbolHandle func = findSymbolNode.execute(name, packageName, rns); if (func == DLL.SYMBOL_NOT_FOUND) { - errorProfile.enter(); - throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, name); + throw error(RError.Message.C_SYMBOL_NOT_IN_TABLE, name); } return callRFFINode.execute(new NativeCallInfo(name, func, rns.getDllInfo()), args.getArguments()); } @Fallback protected Object dotCallFallback(Object fobj, @SuppressWarnings("unused") Object args, @SuppressWarnings("unused") Object packageName) { - throw fallback(fobj); + throw fallback(this, fobj); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java index d10efffa16e25c225bdecc3541acd60262ca89f1..93d2a214721c73a0d532933585bf56ebb6fed4ce 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java @@ -27,7 +27,7 @@ import com.oracle.truffle.r.runtime.ffi.RApplRFFI; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; public abstract class Dqrcf extends RExternalBuiltinNode.Arg8 { - @Child private RApplRFFI.RApplRFFINode rApplRFFINode = RFFIFactory.getRFFI().getRApplRFFI().createRApplRFFINode(); + @Child private RApplRFFI.DqrcfNode dqcrfNode = RFFIFactory.getRFFI().getRApplRFFI().createDqrcfNode(); private static final String E = RRuntime.NAMES_ATTR_EMPTY_VALUE; private static final RStringVector DQRCF_NAMES = RDataFactory.createStringVector(new String[]{E, E, E, E, E, E, "coef", "info"}, RDataFactory.COMPLETE_VECTOR); @@ -52,7 +52,7 @@ public abstract class Dqrcf extends RExternalBuiltinNode.Arg8 { double[] y = yVec.materialize().getDataTemp(); double[] b = bVec.materialize().getDataTemp(); int[] info = infoVec.materialize().getDataTemp(); - rApplRFFINode.dqrcf(x, nx, k, qraux, y, ny, b, info); + dqcrfNode.execute(x, nx, k, qraux, y, ny, b, info); RDoubleVector coef = RDataFactory.createDoubleVector(b, RDataFactory.COMPLETE_VECTOR); coef.copyAttributesFrom(bVec); // @formatter:off @@ -70,8 +70,7 @@ public abstract class Dqrcf extends RExternalBuiltinNode.Arg8 { return RDataFactory.createList(data, DQRCF_NAMES); } catch (ClassCastException | ArrayIndexOutOfBoundsException ex) { - errorProfile.enter(); - throw RError.error(this, RError.Message.INCORRECT_ARG, "dqrcf"); + throw error(RError.Message.INCORRECT_ARG, "dqrcf"); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java index a188007010dd4331fb089dc8b1b4600b7426b041..b546af27357097d5925f084a10af04b9f5b85cd4 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java @@ -26,7 +26,7 @@ import com.oracle.truffle.r.runtime.ffi.RApplRFFI; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; public abstract class Dqrdc2 extends RExternalBuiltinNode.Arg9 { - @Child private RApplRFFI.RApplRFFINode rApplRFFINode = RFFIFactory.getRFFI().getRApplRFFI().createRApplRFFINode(); + @Child private RApplRFFI.Dqrdc2Node dqrdc2Node = RFFIFactory.getRFFI().getRApplRFFI().createDqrdc2Node(); private static final String E = RRuntime.NAMES_ATTR_EMPTY_VALUE; private static final RStringVector DQRDC2_NAMES = RDataFactory.createStringVector(new String[]{"qr", E, E, E, E, "rank", "qraux", "pivot", E}, RDataFactory.COMPLETE_VECTOR); @@ -57,7 +57,7 @@ public abstract class Dqrdc2 extends RExternalBuiltinNode.Arg9 { int[] rank = rankVec.materialize().getDataTemp(); double[] qraux = qrauxVec.materialize().getDataTemp(); int[] pivot = pivotVec.materialize().getDataTemp(); - rApplRFFINode.dqrdc2(x, ldx, n, p, tol, rank, qraux, pivot, workVec.materialize().getDataCopy()); + dqrdc2Node.execute(x, ldx, n, p, tol, rank, qraux, pivot, workVec.materialize().getDataCopy()); // @formatter:off Object[] data = new Object[]{ RDataFactory.createDoubleVector(x, RDataFactory.COMPLETE_VECTOR, getDimNode.getDimensions(xVec)), diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Fft.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Fft.java index aeb884a6112ddfb01ba9f6c767fd03a5ae12f1e5..401b82d01e59464780107515a1de178bd3ec662d 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Fft.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Fft.java @@ -11,6 +11,8 @@ */ package com.oracle.truffle.r.nodes.builtin.base.foreign; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; + import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; @@ -29,7 +31,7 @@ public abstract class Fft extends RExternalBuiltinNode.Arg2 { static { Casts casts = new Casts(Fft.class); - casts.arg(0).mustNotBeNull().asComplexVector(false, true, false); + casts.arg(0).mustNotBeMissing().mustBe(nullValue().not()).asComplexVector(false, true, false); casts.arg(1).mustNotBeNull().asLogicalVector().findFirst().map(Predef.toBoolean()); } @@ -51,8 +53,7 @@ public abstract class Fft extends RExternalBuiltinNode.Arg2 { int n = zVec.getLength(); factorNode.execute(n, maxf, maxp); if (maxf[0] == 0) { - errorProfile.enter(); - throw RError.error(this, RError.Message.FFT_FACTORIZATION); + throw error(RError.Message.FFT_FACTORIZATION); } double[] work = new double[4 * maxf[0]]; int[] iwork = new int[maxp[0]]; @@ -66,8 +67,7 @@ public abstract class Fft extends RExternalBuiltinNode.Arg2 { if (d[i] > 1) { factorNode.execute(d[i], maxf, maxp); if (maxf[0] == 0) { - errorProfile.enter(); - throw RError.error(this, RError.Message.FFT_FACTORIZATION); + throw error(RError.Message.FFT_FACTORIZATION); } if (maxf[0] > maxmaxf) { maxmaxf = maxf[0]; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java index d3d6625fa2359679f28b4d1dc87917ff036161e7..afdff5f5bcce8fd1e78e753c3aff002b74190c65 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java @@ -20,12 +20,12 @@ 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.frame.VirtualFrame; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.base.foreign.LookupAdapter.ExtractNativeCallInfoNode; +import com.oracle.truffle.r.nodes.builtin.base.foreign.LookupAdapterFactory.ExtractNativeCallInfoNodeGen; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; @@ -52,7 +52,7 @@ import com.oracle.truffle.r.runtime.ffi.RFFIFactory; */ public class FortranAndCFunctions { - protected abstract static class CRFFIAdapter extends LookupAdapter { + protected abstract static class CRFFIAdapter extends RBuiltinNode.Arg6 { private static final int SCALAR_DOUBLE = 0; private static final int SCALAR_INT = 1; private static final int SCALAR_LOGICAL = 2; @@ -62,6 +62,7 @@ public class FortranAndCFunctions { private static final int VECTOR_LOGICAL = 12; @SuppressWarnings("unused") private static final int VECTOR_STRING = 12; + @Child protected ExtractNativeCallInfoNode extractSymbolInfo = ExtractNativeCallInfoNodeGen.create(); @Child private CRFFI.InvokeCNode invokeCNode = RFFIFactory.getRFFI().getCRFFI().createInvokeCNode(); @Override @@ -107,7 +108,7 @@ public class FortranAndCFunctions { argTypes[i] = SCALAR_LOGICAL; nativeArgs[i] = checkNAs(node, i + 1, new int[]{RRuntime.isNA((byte) arg) ? RRuntime.INT_NA : (byte) arg}); } else { - throw RError.error(node, RError.Message.UNIMPLEMENTED_ARG_TYPE, i + 1); + throw node.error(RError.Message.UNIMPLEMENTED_ARG_TYPE, i + 1); } } invokeCNode.execute(nativeCallInfo, nativeArgs); @@ -156,7 +157,7 @@ public class FortranAndCFunctions { CompilerAsserts.neverPartOfCompilation(); for (int i = 0; i < data.length; i++) { if (RRuntime.isNA(data[i])) { - throw RError.error(node, RError.Message.NA_IN_FOREIGN_FUNCTION_CALL, argIndex); + throw node.error(RError.Message.NA_IN_FOREIGN_FUNCTION_CALL, argIndex); } } return data; @@ -166,7 +167,7 @@ public class FortranAndCFunctions { CompilerAsserts.neverPartOfCompilation(); for (int i = 0; i < data.length; i++) { if (!RRuntime.isFinite(data[i])) { - throw RError.error(node, RError.Message.NA_NAN_INF_IN_FOREIGN_FUNCTION_CALL, argIndex); + throw node.error(RError.Message.NA_NAN_INF_IN_FOREIGN_FUNCTION_CALL, argIndex); } } return data; @@ -190,7 +191,7 @@ public class FortranAndCFunctions { * FastR, otherwise the .Fortran interface uses the machinery that implements the .C interface. */ @RBuiltin(name = ".Fortran", kind = PRIMITIVE, parameterNames = {".NAME", "...", "NAOK", "DUP", "PACKAGE", "ENCODING"}, behavior = COMPLEX) - public abstract static class Fortran extends CRFFIAdapter { + public abstract static class Fortran extends CRFFIAdapter implements Lookup { static { Casts.noCasts(Fortran.class); @@ -198,8 +199,8 @@ public class FortranAndCFunctions { @Override @TruffleBoundary - protected RExternalBuiltinNode lookupBuiltin(RList symbol) { - switch (lookupName(symbol)) { + public RExternalBuiltinNode lookupBuiltin(RList symbol) { + switch (LookupAdapter.lookupName(symbol)) { case "dqrdc2": return Dqrdc2.create(); case "dqrcf": @@ -220,20 +221,18 @@ public class FortranAndCFunctions { @Specialization(guards = "lookupBuiltin(symbol) == null") protected RList c(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, @SuppressWarnings("unused") Object rPackage, @SuppressWarnings("unused") RMissing encoding) { - NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol); + NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(frame, symbol); return dispatch(this, nativeCallInfo, naok, dup, args); } @Specialization protected RList c(RAbstractStringVector symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, @SuppressWarnings("unused") RMissing encoding, - @Cached("create()") DLL.RFindSymbolNode findSymbolNode, - @Cached("create()") BranchProfile errorProfile) { - String libName = checkPackageArg(rPackage, errorProfile); + @Cached("create()") DLL.RFindSymbolNode findSymbolNode) { + String libName = LookupAdapter.checkPackageArg(rPackage); DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.Fortran, null, null); DLL.SymbolHandle func = findSymbolNode.execute(symbol.getDataAt(0), libName, rns); if (func == DLL.SYMBOL_NOT_FOUND) { - errorProfile.enter(); - throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, symbol); + throw error(RError.Message.C_SYMBOL_NOT_IN_TABLE, symbol); } return dispatch(this, new NativeCallInfo(symbol.getDataAt(0), func, rns.getDllInfo()), naok, dup, args); } @@ -241,7 +240,7 @@ public class FortranAndCFunctions { @SuppressWarnings("unused") @Fallback protected Object fallback(Object symbol, Object args, Object naok, Object dup, Object rPackage, Object encoding) { - throw fallback(symbol); + throw LookupAdapter.fallback(this, symbol); } } @@ -252,37 +251,26 @@ public class FortranAndCFunctions { Casts.noCasts(DotC.class); } - @Override - @TruffleBoundary - protected RExternalBuiltinNode lookupBuiltin(RList symbol) { - throw RInternalError.shouldNotReachHere(); - } - - @SuppressWarnings("unused") @Specialization - protected RList c(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, RMissing encoding) { - NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol); + protected RList c(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, @SuppressWarnings("unused") Object rPackage, @SuppressWarnings("unused") RMissing encoding) { + NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(frame, symbol); return dispatch(this, nativeCallInfo, naok, dup, args); } - @SuppressWarnings("unused") @Specialization - protected RList c(RAbstractStringVector symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, RMissing encoding, - @Cached("create()") DLL.RFindSymbolNode findSymbolNode, - @Cached("create()") BranchProfile errorProfile) { + protected RList c(RAbstractStringVector symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, @SuppressWarnings("unused") RMissing encoding, + @Cached("create()") DLL.RFindSymbolNode findSymbolNode) { String libName = null; if (!(rPackage instanceof RMissing)) { libName = RRuntime.asString(rPackage); if (libName == null) { - errorProfile.enter(); - throw RError.error(this, RError.Message.ARGUMENT_MUST_BE_STRING, "PACKAGE"); + throw error(RError.Message.ARGUMENT_MUST_BE_STRING, "PACKAGE"); } } DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.C, null, null); DLL.SymbolHandle func = findSymbolNode.execute(symbol.getDataAt(0), libName, rns); if (func == DLL.SYMBOL_NOT_FOUND) { - errorProfile.enter(); - throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, symbol); + throw error(RError.Message.C_SYMBOL_NOT_IN_TABLE, symbol); } return dispatch(this, new NativeCallInfo(symbol.getDataAt(0), func, rns.getDllInfo()), naok, dup, args); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java index e71e6060a33c7377ab27cadcb99ab23d95b9043a..49bcba78821d3eab1788b512a52a45eb64db657e 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java @@ -28,7 +28,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.library.stats.RandFunctionsNodes; import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode; @@ -51,6 +50,11 @@ import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; + +interface Lookup { + RExternalBuiltinNode lookupBuiltin(RList symbol); +} /** * Locator for "builtin" package function implementations. The "builtin" packages contain many @@ -59,8 +63,8 @@ import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; * symbol, created when the package is loaded and stored in the namespace environment of the * package, that is a list-valued object. Evidently these "builtins" are somewhat similar to the * {@code .Primitive} and {@code .Internal} builtins and, similarly, most of these are - * re-implemented in Java in FastR. The {@link #lookupBuiltin(RList)} method checks the name in the - * list object and returns the {@link RExternalBuiltinNode} that implements the function, or + * re-implemented in Java in FastR. The {@link Lookup#lookupBuiltin(RList)} method checks the name + * in the list object and returns the {@link RExternalBuiltinNode} that implements the function, or * {@code null}. A {@code null} result implies that the builtin is not implemented in Java, but * called directly via the FFI interface, which is only possible for functions that use the FFI in a * way that FastR can handle. @@ -68,8 +72,8 @@ import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; * This class also handles the "lookup" of the {@link NativeCallInfo} data for builtins that are * still implemented by native code. */ -abstract class LookupAdapter extends RBuiltinNode { - @Child private ExtractNativeCallInfoNode extractSymbolInfoNode = ExtractNativeCallInfoNodeGen.create(); +abstract class LookupAdapter extends RBuiltinNode.Arg3 implements Lookup { + @Child protected ExtractNativeCallInfoNode extractSymbolInfo = ExtractNativeCallInfoNodeGen.create(); protected static class UnimplementedExternal extends RExternalBuiltinNode { private final String name; @@ -88,11 +92,9 @@ abstract class LookupAdapter extends RBuiltinNode { } } - protected abstract RExternalBuiltinNode lookupBuiltin(RList symbol); - private static final String UNKNOWN_EXTERNAL_BUILTIN = "UNKNOWN_EXTERNAL_BUILTIN"; - protected static String lookupName(RList symbol) { + public static String lookupName(RList symbol) { CompilerAsserts.neverPartOfCompilation(); if (symbol.getNames() != null) { RAbstractStringVector names = symbol.getNames(); @@ -107,33 +109,28 @@ abstract class LookupAdapter extends RBuiltinNode { } @TruffleBoundary - protected RuntimeException fallback(Object symbol) { + protected static RuntimeException fallback(Lookup lookup, Object symbol) { String name = null; if (symbol instanceof RList) { name = lookupName((RList) symbol); name = name == UNKNOWN_EXTERNAL_BUILTIN ? null : name; - if (name != null && lookupBuiltin((RList) symbol) != null) { + if (name != null && lookup.lookupBuiltin((RList) symbol) != null) { /* * if we reach this point, then the cache saw a different value for f. the lists * that contain the information about native calls are never expected to change. */ - throw RInternalError.shouldNotReachHere("fallback reached for " + getRBuiltin().name() + " " + name); + throw RInternalError.shouldNotReachHere("fallback reached for " + lookup + " " + name); } } - throw RError.nyi(this, getRBuiltin().name() + " specialization failure: " + (name == null ? "<unknown>" : name)); - } - - protected NativeCallInfo extractSymbolInfo(VirtualFrame frame, RList symbol) { - return (NativeCallInfo) extractSymbolInfoNode.execute(frame, symbol); + throw RError.nyi((RBaseNode) lookup, lookup + " specialization failure: " + (name == null ? "<unknown>" : name)); } - protected String checkPackageArg(Object rPackage, BranchProfile errorProfile) { + public static String checkPackageArg(Object rPackage) { String libName = null; if (!(rPackage instanceof RMissing)) { libName = RRuntime.asString(rPackage); if (libName == null) { - errorProfile.enter(); - throw RError.error(this, RError.Message.ARGUMENT_MUST_BE_STRING, "PACKAGE"); + throw RError.error(RError.SHOW_CALLER, RError.Message.ARGUMENT_MUST_BE_STRING, "PACKAGE"); } } return libName; @@ -149,10 +146,10 @@ abstract class LookupAdapter extends RBuiltinNode { @Child private ExtractVectorNode packageExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); @Child private ExtractVectorNode infoExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); - protected abstract Object execute(VirtualFrame frame, RList symbol); + protected abstract NativeCallInfo execute(VirtualFrame frame, RList symbol); @Specialization - protected Object extractNativeCallInfo(VirtualFrame frame, RList symbol) { + protected NativeCallInfo extractNativeCallInfo(VirtualFrame frame, RList symbol) { if (nameExtract == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); nameExtract = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true)); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ReadTableHead.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ReadTableHead.java index 71b34f14650b59a0124a88b485e15c153e94a17f..9c3477a46d7a568cbccfa619e0074fff5027a88d 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ReadTableHead.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ReadTableHead.java @@ -12,9 +12,12 @@ package com.oracle.truffle.r.nodes.builtin.base.foreign; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; @@ -28,18 +31,51 @@ public abstract class ReadTableHead extends RExternalBuiltinNode.Arg7 { Casts casts = new Casts(ReadTableHead.class); casts.arg(0).defaultError(Message.INVALID_CONNECTION).mustNotBeNull().asIntegerVector().findFirst(); casts.arg(1).mustNotBeNull().asIntegerVector().findFirst(); + casts.arg(2).mustNotBeMissing().mustBe(Predef.stringValue()).asStringVector().findFirst(); + casts.arg(3).mustNotBeMissing().mustBe(Predef.logicalValue()).asLogicalVector().findFirst().map(Predef.toBoolean()); + casts.arg(4).mustNotBeMissing().mustBe(Predef.stringValue()).asStringVector().findFirst(); + casts.arg(5).mustNotBeMissing().mustBe(Predef.stringValue()).asStringVector().findFirst(); + casts.arg(6).mustNotBeMissing().mustBe(Predef.logicalValue()).asLogicalVector().findFirst().map(Predef.toBoolean()); } @Specialization @TruffleBoundary - public RAbstractStringVector read(int con, int nlines, @SuppressWarnings("unused") Object commentChar, @SuppressWarnings("unused") Object blankLinesSkip, - @SuppressWarnings("unused") Object quote, @SuppressWarnings("unused") Object sep, @SuppressWarnings("unused") Object skipNull) { + public RAbstractStringVector read(int con, int nlines, String commentChar, boolean blankLinesSkip, + String quote, String sep, boolean skipNull) { // TODO This is quite incomplete and just uses readLines, which works for some inputs try (RConnection openConn = RConnection.fromIndex(con).forceOpen("r")) { - return RDataFactory.createStringVector(openConn.readLines(nlines, true, false), RDataFactory.COMPLETE_VECTOR); + List<String> lines = new ArrayList<>(nlines); + int totalLines = 0; + while (totalLines < nlines) { + String[] readLines = openConn.readLines(nlines - totalLines, true, skipNull); + if (readLines.length == 0) { + break; + } + + for (int i = 0; i < readLines.length; i++) { + postprocessLine(lines, readLines[i], commentChar, blankLinesSkip, quote, sep); + } + totalLines += lines.size(); + } + + return RDataFactory.createStringVector(lines.toArray(new String[0]), RDataFactory.COMPLETE_VECTOR); } catch (IOException ex) { - errorProfile.enter(); - throw RError.error(this, RError.Message.ERROR_READING_CONNECTION, ex.getMessage()); + throw error(RError.Message.ERROR_READING_CONNECTION, ex.getMessage()); + } + } + + private static void postprocessLine(List<String> lines, String string, String commentChar, boolean blankLinesSkip, @SuppressWarnings("unused") String quote, + @SuppressWarnings("unused") String sep) { + // TODO quote, sep + if (blankLinesSkip && string.isEmpty()) { + return; + } + + if (commentChar != null && !commentChar.isEmpty() && string.startsWith(commentChar)) { + return; } + + // no reason why not to add + lines.add(string); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java index 53cbadf9d42d75f9cc5fa5956c6511d145ff22f8..6c3e454a255f0ae3dd39d2ca24676ba74e8780d5 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java @@ -11,6 +11,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base.foreign; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; @@ -22,11 +23,13 @@ import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.printer.ComplexVectorPrinter; import com.oracle.truffle.r.nodes.builtin.base.printer.DoubleVectorPrinter; +import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; 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.RRuntime; import com.oracle.truffle.r.runtime.conn.RConnection; +import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RComplexVector; import com.oracle.truffle.r.runtime.data.RDoubleVector; @@ -54,9 +57,9 @@ public abstract class WriteTable extends RExternalBuiltinNode.Arg11 { // file casts.arg(1).defaultError(Message.INVALID_CONNECTION).mustNotBeNull().asIntegerVector().findFirst(); // nrows - casts.arg(2).mustNotBeNull().asIntegerVector().findFirst().notNA(); + casts.arg(2).mustNotBeNull().asIntegerVector().findFirst().mustNotBeNA(); // nc - casts.arg(3).mustNotBeNull().asIntegerVector().findFirst().notNA(); + casts.arg(3).mustNotBeNull().asIntegerVector().findFirst().mustNotBeNA(); // rnames casts.arg(4).allowNull().mustBe(stringValue()).asStringVector(); // sep @@ -68,9 +71,9 @@ public abstract class WriteTable extends RExternalBuiltinNode.Arg11 { // dec casts.arg(8).mustBe(stringValue()).asStringVector().findFirst().mustBe(Predef.length(1), RError.Message.GENERIC, "'dec' must be a single character"); // quote - casts.arg(9).mustNotBeNull().asIntegerVector(); + casts.arg(9).mustNotBeMissing().mustBe(nullValue().not()).asIntegerVector(); // qmethod - casts.arg(10).mustNotBeNull().asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg(10).mustNotBeNull().asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } // Transcribed from GnuR, library/utils/src/io.c @@ -92,7 +95,7 @@ public abstract class WriteTable extends RExternalBuiltinNode.Arg11 { } try (RConnection con = RConnection.fromIndex(file).forceOpen("wt")) { String tmp = null; - if (RRuntime.hasRClass(xx, RRuntime.CLASS_DATA_FRAME)) { + if (xx instanceof RAttributable && ClassHierarchyNode.hasClass((RAttributable) xx, RRuntime.CLASS_DATA_FRAME)) { executeDataFrame(con, (RVector<?>) xx, nr, nc, rnames, csep, ceol, cna, cdec, qmethod, quoteCol, quoteRn); } else { /* A matrix */ @@ -105,9 +108,6 @@ public abstract class WriteTable extends RExternalBuiltinNode.Arg11 { } for (int i = 0; i < nr; i++) { - if (i % 1000 == 999) { - // R_CheckUserInterrupt(); - } if (!(rnames instanceof RNull)) { con.writeString(encodeElement2((RAbstractStringVector) rnames, i, quoteRn, qmethod, cdec), false); con.writeString(csep, false); @@ -195,7 +195,7 @@ public abstract class WriteTable extends RExternalBuiltinNode.Arg11 { if (!quote) { return p0; } - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); sb.append('"'); for (int i = 0; i < p0.length(); i++) { char p = p0.charAt(i); @@ -234,7 +234,7 @@ public abstract class WriteTable extends RExternalBuiltinNode.Arg11 { } else if (o instanceof String) { String v = (String) o; return RRuntime.isNA(v) ? cna : encodeStringElement(v, quote, qmethod); - } else if (o instanceof Double) { + } else if (o instanceof RComplex) { RComplex v = (RComplex) o; return RRuntime.isNA(v) ? cna : ComplexVectorPrinter.encodeComplex(v); } else if (o instanceof RRaw) { @@ -286,9 +286,11 @@ public abstract class WriteTable extends RExternalBuiltinNode.Arg11 { throw RInternalError.unimplemented(); } + @TruffleBoundary private static boolean isFactor(RAbstractContainer v) { - for (int i = 0; i < v.getClassHierarchy().getLength(); i++) { - if (v.getClassHierarchy().getDataAt(i).equals("factor")) { + RStringVector hierarchy = ClassHierarchyNode.getClassHierarchy(v); + for (int i = 0; i < hierarchy.getLength(); i++) { + if (hierarchy.getDataAt(i).equals("factor")) { return true; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java index 56d7bb579b090487486b9be09ffcc9f49963bad2..e96fba86dd02eb704a78c76e7a92a9421e242362 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java @@ -31,12 +31,9 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.dsl.TypeSystemReference; -import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; import com.oracle.truffle.r.nodes.access.vector.ExtractListElement; import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode; @@ -62,7 +59,6 @@ import qir.ast.data.QIRTdestr; import qir.ast.data.QIRTnil; import qir.ast.operator.QIRProject; -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) @NodeChild(value = "arguments", type = RNode[].class) abstract class AccessFieldSpecial extends SpecialsUtils.ListFieldSpecialBase { @@ -96,8 +92,7 @@ abstract class AccessFieldSpecial extends SpecialsUtils.ListFieldSpecialBase { } @RBuiltin(name = "$", kind = PRIMITIVE, parameterNames = {"", ""}, dispatch = INTERNAL_GENERIC, behavior = PURE) -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) -public abstract class AccessField extends RBuiltinNode { +public abstract class AccessField extends RBuiltinNode.Arg2 { @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.FIELD_SUBSCRIPT, true); @@ -117,7 +112,7 @@ public abstract class AccessField extends RBuiltinNode { protected Object access(VirtualFrame frame, Object container, String field) { if (!invalidAtomicVector.profile(container instanceof RAbstractListVector) && container instanceof RAbstractVector) { error.enter(); - throw RError.error(this, RError.Message.DOLLAR_ATOMIC_VECTORS); + throw error(RError.Message.DOLLAR_ATOMIC_VECTORS); } else if (container instanceof REnvironment && ((REnvironment) container).get("queryId") != null) { final Object queryId = ((REnvironment) container).get("queryId"); if (queryId != null) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltin.java index 48c2028bde2df0d1f58841ded91aece5ecb2a9b8..90d1260e9a5aedc21d8b9eb2f426d874d762e37b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltin.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltin.java @@ -32,7 +32,12 @@ import com.oracle.truffle.r.runtime.builtins.RBehavior; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "<-", visibility = RVisibility.OFF, kind = PRIMITIVE, parameterNames = {"x", "i"}, behavior = RBehavior.MODIFIES_FRAME) -public abstract class AssignBuiltin extends RBuiltinNode { +public abstract class AssignBuiltin extends RBuiltinNode.Arg2 { + + static { + Casts.noCasts(AssignBuiltin.class); + } + @Specialization protected Object doIt(@SuppressWarnings("unused") Object x, @SuppressWarnings("unused") Object i) { throw RInternalError.unimplemented(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltinEq.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltinEq.java index 26185da3e6973e1a2e97548cfe9a8d98b59b2982..f35dc6cff103578b9bbac9e4bfab330c69551a64 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltinEq.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltinEq.java @@ -32,7 +32,12 @@ import com.oracle.truffle.r.runtime.builtins.RBehavior; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "=", visibility = RVisibility.OFF, kind = PRIMITIVE, parameterNames = {"x", "i"}, behavior = RBehavior.MODIFIES_FRAME) -public abstract class AssignBuiltinEq extends RBuiltinNode { +public abstract class AssignBuiltinEq extends RBuiltinNode.Arg2 { + + static { + Casts.noCasts(AssignBuiltinEq.class); + } + @Specialization protected Object doIt(@SuppressWarnings("unused") Object x, @SuppressWarnings("unused") Object i) { throw RInternalError.unimplemented(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignOuterBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignOuterBuiltin.java index fd990f8ec409867259267a6d9ac4d2a7163a0c7a..35ccfe7cc34a09d1c1a098678d456f83f6e653f2 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignOuterBuiltin.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignOuterBuiltin.java @@ -32,7 +32,12 @@ import com.oracle.truffle.r.runtime.RVisibility; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "<<-", visibility = RVisibility.OFF, kind = PRIMITIVE, parameterNames = {"x", "i"}, behavior = COMPLEX) -public abstract class AssignOuterBuiltin extends RBuiltinNode { +public abstract class AssignOuterBuiltin extends RBuiltinNode.Arg2 { + + static { + Casts.noCasts(AssignOuterBuiltin.class); + } + @Specialization protected Object doIt(@SuppressWarnings("unused") Object x, @SuppressWarnings("unused") Object i) { throw RInternalError.unimplemented(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BraceBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BraceBuiltin.java index 80ff6820346e2e7cf5ccc26d36f2b78fec70d676..2db00345ee186afe2c0f3d3d9f3e0ce4713e91e0 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BraceBuiltin.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BraceBuiltin.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base.infix; +import static com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts.noCasts; import static com.oracle.truffle.r.runtime.RVisibility.CUSTOM; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -32,7 +33,12 @@ import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "{", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) -public abstract class BraceBuiltin extends RBuiltinNode { +public abstract class BraceBuiltin extends RBuiltinNode.Arg1 { + + static { + noCasts(BraceBuiltin.class); + } + @Specialization protected Object doIt(@SuppressWarnings("unused") Object x) { throw RInternalError.unimplemented(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BreakBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BreakBuiltin.java index b4dea21f7484e6fae3bc9130ff148ae5fd745b07..aeea494ef8219d3633a887e6d3ac1b305e8a43c8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BreakBuiltin.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BreakBuiltin.java @@ -31,7 +31,12 @@ import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "break", kind = PRIMITIVE, parameterNames = {"x"}, behavior = COMPLEX) -public abstract class BreakBuiltin extends RBuiltinNode { +public abstract class BreakBuiltin extends RBuiltinNode.Arg1 { + + static { + Casts.noCasts(BreakBuiltin.class); + } + @Specialization protected Object doIt(@SuppressWarnings("unused") Object x) { throw RInternalError.unimplemented(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ForBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ForBuiltin.java index 562c7be2c0d3904260739861cba1ce073d19f457..c9309ab8700e8603c63c56cd4da039820d225cb3 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ForBuiltin.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ForBuiltin.java @@ -32,7 +32,12 @@ import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "for", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) -public abstract class ForBuiltin extends RBuiltinNode { +public abstract class ForBuiltin extends RBuiltinNode.Arg1 { + + static { + Casts.noCasts(ForBuiltin.class); + } + @Specialization protected Object doIt(@SuppressWarnings("unused") Object x) { throw RInternalError.unimplemented(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/FunctionBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/FunctionBuiltin.java index b1ebcae60c1da66b990b936a3fddde3bd9011961..3909ffbb92edc496f1e07f724252dcc77cd3df50 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/FunctionBuiltin.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/FunctionBuiltin.java @@ -31,7 +31,12 @@ import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "function", kind = PRIMITIVE, parameterNames = {"x"}, behavior = READS_FRAME) -public abstract class FunctionBuiltin extends RBuiltinNode { +public abstract class FunctionBuiltin extends RBuiltinNode.Arg1 { + + static { + Casts.noCasts(FunctionBuiltin.class); + } + @Specialization protected Object doIt(@SuppressWarnings("unused") Object x) { throw RInternalError.unimplemented(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/IfBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/IfBuiltin.java index 9c6ebc6058fd1b7a062eeb3146afb6e7194e5c05..0865d2a4e83f619c59b33873c9ae33e0ad97f6ce 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/IfBuiltin.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/IfBuiltin.java @@ -32,7 +32,12 @@ import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "if", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) -public abstract class IfBuiltin extends RBuiltinNode { +public abstract class IfBuiltin extends RBuiltinNode.Arg1 { + + static { + Casts.noCasts(IfBuiltin.class); + } + @Specialization protected Object doIt(@SuppressWarnings("unused") Object x) { throw RInternalError.unimplemented(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/NextBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/NextBuiltin.java index d83ea3512951829db7d2f948c5f530244cf43a32..0fc3d4127437b9b1e9878ddaf672ad86e5102d43 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/NextBuiltin.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/NextBuiltin.java @@ -26,12 +26,18 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.dsl.Specialization; +import static com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts.noCasts; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "next", kind = PRIMITIVE, parameterNames = {"x"}, behavior = COMPLEX) -public abstract class NextBuiltin extends RBuiltinNode { +public abstract class NextBuiltin extends RBuiltinNode.Arg1 { + + static { + noCasts(NextBuiltin.class); + } + @Specialization protected Object doIt(@SuppressWarnings("unused") Object x) { throw RInternalError.unimplemented(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ParenBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ParenBuiltin.java index 08d6f1a6243c1359527a535f4e7d1eae0f508238..dd90c743d349537dd358bb36d417c7b0ff13368a 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ParenBuiltin.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ParenBuiltin.java @@ -50,7 +50,7 @@ final class ParensSpecial extends RNode { } @RBuiltin(name = "(", kind = PRIMITIVE, parameterNames = {""}, visibility = ON, behavior = PURE) -public final class ParenBuiltin extends RBuiltinNode { +public final class ParenBuiltin extends RBuiltinNode.Arg1 { static { Casts.noCasts(ParenBuiltin.class); @@ -64,7 +64,7 @@ public final class ParenBuiltin extends RBuiltinNode { } @Override - public Object executeBuiltin(VirtualFrame frame, Object... args) { - return args[0]; + public Object execute(VirtualFrame frame, Object arg) { + return arg; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ProfiledSpecialsUtils.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ProfiledSpecialsUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..4d9d655c0723c28762833aa930d565f84a2d24f9 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ProfiledSpecialsUtils.java @@ -0,0 +1,231 @@ +/* + * 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.nodes.builtin.base.infix; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.NodeChild; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertIndex; +import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertValue; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.nodes.RNode; + +public class ProfiledSpecialsUtils { + + @NodeChild(value = "vector", type = RNode.class) + @NodeChild(value = "index", type = ConvertIndex.class) + protected abstract static class ProfiledSubscriptSpecialBase extends RNode { + + protected static final int CACHE_LIMIT = 3; + protected final boolean inReplacement; + + @Child protected SubscriptSpecialBase defaultAccessNode; + + protected ProfiledSubscriptSpecialBase(boolean inReplacement) { + this.inReplacement = inReplacement; + } + + protected SubscriptSpecialBase createAccessNode() { + throw RInternalError.shouldNotReachHere(); + } + + @Specialization(limit = "CACHE_LIMIT", guards = "vector.getClass() == clazz") + public Object access(VirtualFrame frame, RAbstractVector vector, Object index, + @Cached(value = "vector.getClass()") Class<?> clazz, + @Cached("createAccessNode()") SubscriptSpecialBase accessNodeCached) { + return accessNodeCached.execute(frame, clazz.cast(vector), index); + } + + @Specialization(replaces = "access") + public Object accessGeneric(VirtualFrame frame, Object vector, Object index) { + if (defaultAccessNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + defaultAccessNode = insert(createAccessNode()); + } + return defaultAccessNode.execute(frame, vector, index); + } + } + + public abstract static class ProfiledSubscriptSpecial extends ProfiledSubscriptSpecialBase { + + protected ProfiledSubscriptSpecial(boolean inReplacement) { + super(inReplacement); + } + + @Override + protected SubscriptSpecialBase createAccessNode() { + return SubscriptSpecialNodeGen.create(inReplacement); + } + } + + public abstract static class ProfiledSubsetSpecial extends ProfiledSubscriptSpecialBase { + + protected ProfiledSubsetSpecial(boolean inReplacement) { + super(inReplacement); + } + + @Override + protected SubscriptSpecialBase createAccessNode() { + return SubsetSpecialNodeGen.create(inReplacement); + } + } + + @NodeChild(value = "vector", type = RNode.class) + @NodeChild(value = "index1", type = ConvertIndex.class) + @NodeChild(value = "index2", type = ConvertIndex.class) + public abstract static class ProfiledSubscriptSpecial2Base extends RNode { + + protected static final int CACHE_LIMIT = 3; + protected final boolean inReplacement; + + @Child protected SubscriptSpecial2Base defaultAccessNode; + + protected ProfiledSubscriptSpecial2Base(boolean inReplacement) { + this.inReplacement = inReplacement; + } + + protected SubscriptSpecial2Base createAccessNode() { + throw RInternalError.shouldNotReachHere(); + } + + @Specialization(limit = "CACHE_LIMIT", guards = "vector.getClass() == clazz") + public Object access(VirtualFrame frame, RAbstractVector vector, Object index1, Object index2, + @Cached("vector.getClass()") Class<?> clazz, + @Cached("createAccessNode()") SubscriptSpecial2Base accessNodeCached) { + return accessNodeCached.execute(frame, clazz.cast(vector), index1, index2); + } + + @Specialization(replaces = "access") + public Object accessGeneric(VirtualFrame frame, Object vector, Object index1, Object index2) { + if (defaultAccessNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + defaultAccessNode = insert(createAccessNode()); + } + return defaultAccessNode.execute(frame, vector, index1, index2); + } + + } + + public abstract static class ProfiledSubscriptSpecial2 extends ProfiledSubscriptSpecial2Base { + + protected ProfiledSubscriptSpecial2(boolean inReplacement) { + super(inReplacement); + } + + @Override + protected SubscriptSpecial2Base createAccessNode() { + return SubscriptSpecial2NodeGen.create(inReplacement); + } + + } + + public abstract static class ProfiledSubsetSpecial2 extends ProfiledSubscriptSpecial2Base { + + protected ProfiledSubsetSpecial2(boolean inReplacement) { + super(inReplacement); + } + + @Override + protected SubscriptSpecial2Base createAccessNode() { + return SubsetSpecial2NodeGen.create(inReplacement); + } + } + + @NodeChild(value = "vector", type = RNode.class) + @NodeChild(value = "index", type = ConvertIndex.class) + @NodeChild(value = "value", type = ConvertValue.class) + public abstract static class ProfiledUpdateSubscriptSpecialBase extends RNode { + + protected static final int CACHE_LIMIT = 3; + protected final boolean inReplacement; + + public abstract Object execute(VirtualFrame frame, Object vector, Object index, Object value); + + @Child protected UpdateSubscriptSpecial defaultAccessNode; + + protected ProfiledUpdateSubscriptSpecialBase(boolean inReplacement) { + this.inReplacement = inReplacement; + } + + protected UpdateSubscriptSpecial createAccessNode() { + return UpdateSubscriptSpecialNodeGen.create(inReplacement); + } + + @Specialization(limit = "CACHE_LIMIT", guards = "vector.getClass() == clazz") + public Object access(VirtualFrame frame, Object vector, Object index, Object value, + @Cached("vector.getClass()") Class<?> clazz, + @Cached("createAccessNode()") UpdateSubscriptSpecial accessNodeCached) { + return accessNodeCached.execute(frame, clazz.cast(vector), index, value); + } + + @Specialization(replaces = "access") + public Object accessGeneric(VirtualFrame frame, Object vector, Object index, Object value) { + if (defaultAccessNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + defaultAccessNode = insert(createAccessNode()); + } + return defaultAccessNode.execute(frame, vector, index, value); + } + } + + @NodeChild(value = "vector", type = RNode.class) + @NodeChild(value = "index1", type = ConvertIndex.class) + @NodeChild(value = "index2", type = ConvertIndex.class) + @NodeChild(value = "value", type = ConvertValue.class) + public abstract static class ProfiledUpdateSubscriptSpecial2 extends RNode { + + protected static final int CACHE_LIMIT = 3; + protected final boolean inReplacement; + + public abstract Object execute(VirtualFrame frame, Object vector, Object index1, Object index2, Object value); + + @Child protected UpdateSubscriptSpecial2 defaultAccessNode; + + protected ProfiledUpdateSubscriptSpecial2(boolean inReplacement) { + this.inReplacement = inReplacement; + } + + protected UpdateSubscriptSpecial2 createAccessNode() { + return UpdateSubscriptSpecial2NodeGen.create(inReplacement); + } + + @Specialization(limit = "CACHE_LIMIT", guards = "vector.getClass() == clazz") + public Object access(VirtualFrame frame, Object vector, Object index1, Object index2, Object value, + @Cached("vector.getClass()") Class<?> clazz, + @Cached("createAccessNode()") UpdateSubscriptSpecial2 accessNodeCached) { + return accessNodeCached.execute(frame, clazz.cast(vector), index1, index2, value); + } + + @Specialization(replaces = "access") + public Object accessGeneric(VirtualFrame frame, Object vector, Object index1, Object index2, Object value) { + if (defaultAccessNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + defaultAccessNode = insert(createAccessNode()); + } + return defaultAccessNode.execute(frame, vector, index1, index2, value); + } + } +} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/RepeatBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/RepeatBuiltin.java index 5b612ffdcf8b3c09076f245bda69d7fb4d393ef7..73ea958d487584dad35969a4e6d8bca087ab506d 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/RepeatBuiltin.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/RepeatBuiltin.java @@ -32,7 +32,12 @@ import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "repeat", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) -public abstract class RepeatBuiltin extends RBuiltinNode { +public abstract class RepeatBuiltin extends RBuiltinNode.Arg1 { + + static { + Casts.noCasts(RepeatBuiltin.class); + } + @Specialization protected Object doIt(@SuppressWarnings("unused") Object x) { throw RInternalError.unimplemented(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java index 501753254b73bcfac9933452900ba9ae7c2b3929..569af73be2fc13c8a9178766d0a4c773b7b30f4f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java @@ -24,23 +24,24 @@ package com.oracle.truffle.r.nodes.builtin.base.infix; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.dsl.TypeSystemReference; -import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.nodes.NodeInfo; -import com.oracle.truffle.api.profiles.ValueProfile; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ConvertIndexNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ConvertValueNodeGen; import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; +import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen; import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @@ -50,6 +51,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; * @see com.oracle.truffle.r.runtime.builtins.RSpecialFactory */ class SpecialsUtils { + private static final String valueArgName = "value".intern(); public static boolean isCorrectUpdateSignature(ArgumentsSignature signature) { @@ -64,8 +66,9 @@ class SpecialsUtils { /** * Common code shared between specials doing subset/subscript related operation. */ - @TypeSystemReference(EmptyTypeSystemFlatLayout.class) - abstract static class SubscriptSpecialCommon extends RNode { + abstract static class SubscriptSpecialCommon extends Node { + + @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false); protected final boolean inReplacement; @@ -73,6 +76,10 @@ class SpecialsUtils { this.inReplacement = inReplacement; } + protected boolean simpleVector(RAbstractVector vector) { + return classHierarchy.execute(vector) == null; + } + /** * Checks whether the given (1-based) index is valid for the given vector. */ @@ -90,7 +97,6 @@ class SpecialsUtils { } } - @TypeSystemReference(EmptyTypeSystemFlatLayout.class) abstract static class SubscriptSpecial2Common extends SubscriptSpecialCommon { protected SubscriptSpecial2Common(boolean inReplacement) { @@ -115,7 +121,6 @@ class SpecialsUtils { /** * Common code shared between specials accessing/updating fields. */ - @TypeSystemReference(EmptyTypeSystemFlatLayout.class) abstract static class ListFieldSpecialBase extends RNode { @Child private ClassHierarchyNode hierarchyNode = ClassHierarchyNode.create(); @@ -149,30 +154,8 @@ class SpecialsUtils { } } - @NodeInfo(cost = NodeCost.NONE) - public static final class ProfiledValue extends RBaseNode { - - private final ValueProfile profile = ValueProfile.createClassProfile(); - - @Child private RNode delegate; - - protected ProfiledValue(RNode delegate) { - this.delegate = delegate; - } - - public Object execute(VirtualFrame frame) { - return profile.profile(delegate.execute(frame)); - } - - @Override - protected RSyntaxNode getRSyntaxNode() { - return delegate.asRSyntaxNode(); - } - } - @NodeInfo(cost = NodeCost.NONE) @NodeChild(value = "delegate", type = RNode.class) - @TypeSystemReference(EmptyTypeSystemFlatLayout.class) public abstract static class ConvertIndex extends RNode { protected abstract RNode getDelegate(); @@ -210,11 +193,50 @@ class SpecialsUtils { } } - public static ProfiledValue profile(RNode value) { - return new ProfiledValue(value); + @NodeInfo(cost = NodeCost.NONE) + @NodeChild(value = "delegate", type = RNode.class) + public abstract static class ConvertValue extends RNode { + + protected abstract RNode getDelegate(); + + @Specialization + protected static int convert(int value) { + return value; + } + + @Specialization + protected static double convert(double value) { + return value; + } + + @Specialization(guards = {"value.getLength() == 1", "hierarchyNode.execute(value) == null"}) + protected static int convertIntVector(RIntVector value, + @Cached("create()") @SuppressWarnings("unused") ClassHierarchyNode hierarchyNode) { + return value.getDataAt(0); + } + + @Specialization(guards = {"value.getLength() == 1", "hierarchyNode.execute(value) == null"}) + protected static double convertDoubleVector(RDoubleVector value, + @Cached("create()") @SuppressWarnings("unused") ClassHierarchyNode hierarchyNode) { + return value.getDataAt(0); + } + + @Specialization(replaces = {"convertIntVector", "convertDoubleVector"}) + protected Object convert(Object value) { + return value; + } + + @Override + protected RSyntaxNode getRSyntaxNode() { + return getDelegate().asRSyntaxNode(); + } } public static ConvertIndex convertIndex(RNode value) { return ConvertIndexNodeGen.create(value); } + + public static ConvertValue convertValue(RNode value) { + return ConvertValueNodeGen.create(value); + } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java index 144f70966bb6ff034fb6de41078cce871018e1e5..113fccddad113db8997093d4124656df4e8133d5 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java @@ -23,14 +23,12 @@ package com.oracle.truffle.r.nodes.builtin.base.infix; import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertIndex; -import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.profile; import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; -import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; @@ -38,12 +36,11 @@ import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; import com.oracle.truffle.r.nodes.access.vector.ExtractListElement; import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.base.infix.ProfiledSpecialsUtilsFactory.ProfiledSubscriptSpecial2NodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.ProfiledSpecialsUtilsFactory.ProfiledSubscriptSpecialNodeGen; import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertIndex; -import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ProfiledValue; import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpecial2Common; import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpecialCommon; -import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; -import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; @@ -54,7 +51,7 @@ import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RLogical; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RTypesFlatLayout; +import com.oracle.truffle.r.runtime.data.RTypes; 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.RAbstractLogicalVector; @@ -65,19 +62,13 @@ import com.oracle.truffle.r.runtime.nodes.RNode; /** * Subscript code for vectors minus list is the same as subset code, this class allows sharing it. */ -@NodeChild(value = "vector", type = ProfiledValue.class) -@NodeChild(value = "index", type = ConvertIndex.class) abstract class SubscriptSpecialBase extends SubscriptSpecialCommon { protected SubscriptSpecialBase(boolean inReplacement) { super(inReplacement); } - @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false); - - protected boolean simpleVector(RAbstractVector vector) { - return classHierarchy.execute(vector) == null; - } + protected abstract Object execute(VirtualFrame frame, Object vec, Object index); @Specialization(guards = {"simpleVector(vector)", "isValidIndex(vector, index)"}) protected int access(RAbstractIntVector vector, int index) { @@ -104,26 +95,13 @@ abstract class SubscriptSpecialBase extends SubscriptSpecialCommon { /** * Subscript code for matrices minus list is the same as subset code, this class allows sharing it. */ -@NodeChild(value = "vector", type = ProfiledValue.class) -@NodeChild(value = "index1", type = ConvertIndex.class) -@NodeChild(value = "index2", type = ConvertIndex.class) abstract class SubscriptSpecial2Base extends SubscriptSpecial2Common { protected SubscriptSpecial2Base(boolean inReplacement) { super(inReplacement); } - @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false); - - protected abstract ProfiledValue getVector(); - - protected abstract ConvertIndex getIndex1(); - - protected abstract ConvertIndex getIndex2(); - - protected boolean simpleVector(RAbstractVector vector) { - return classHierarchy.execute(vector) == null; - } + public abstract Object execute(VirtualFrame frame, Object vector, Object index1, Object index2); @Specialization(guards = {"simpleVector(vector)", "isValidIndex(vector, index1, index2)"}) protected int access(RAbstractIntVector vector, int index1, int index2) { @@ -168,6 +146,10 @@ abstract class SubscriptSpecial extends SubscriptSpecialBase { @Cached("createAccess()") ExtractVectorNode extract) { return extract.apply(frame, vector, new Object[]{index}, RRuntime.LOGICAL_TRUE, RLogical.TRUE); } + + public static RNode create(boolean inReplacement, RNode profiledVector, ConvertIndex index) { + return ProfiledSubscriptSpecialNodeGen.create(inReplacement, profiledVector, index); + } } abstract class SubscriptSpecial2 extends SubscriptSpecial2Base { @@ -181,11 +163,15 @@ abstract class SubscriptSpecial2 extends SubscriptSpecial2Base { @Cached("create()") ExtractListElement extract) { return extract.execute(vector, matrixIndex(vector, index1, index2)); } + + public static RNode create(boolean inReplacement, RNode vectorNode, ConvertIndex index1, ConvertIndex index2) { + return ProfiledSubscriptSpecial2NodeGen.create(inReplacement, vectorNode, index1, index2); + } } @RBuiltin(name = "[[", kind = PRIMITIVE, parameterNames = {"x", "...", "exact", "drop"}, dispatch = INTERNAL_GENERIC, behavior = PURE) -@TypeSystemReference(RTypesFlatLayout.class) -public abstract class Subscript extends RBuiltinNode { +@TypeSystemReference(RTypes.class) +public abstract class Subscript extends RBuiltinNode.Arg4 { @RBuiltin(name = ".subset2", kind = PRIMITIVE, parameterNames = {"x", "...", "exact", "drop"}, behavior = PURE) public abstract class DefaultBuiltin { @@ -199,9 +185,9 @@ public abstract class Subscript extends RBuiltinNode { public static RNode special(ArgumentsSignature signature, RNode[] arguments, boolean inReplacement) { if (signature.getNonNullCount() == 0) { if (arguments.length == 2) { - return SubscriptSpecialNodeGen.create(inReplacement, profile(arguments[0]), convertIndex(arguments[1])); + return SubscriptSpecial.create(inReplacement, arguments[0], convertIndex(arguments[1])); } else if (arguments.length == 3) { - return SubscriptSpecial2NodeGen.create(inReplacement, profile(arguments[0]), convertIndex(arguments[1]), convertIndex(arguments[2])); + return SubscriptSpecial2.create(inReplacement, arguments[0], convertIndex(arguments[1]), convertIndex(arguments[2])); } } return null; @@ -223,13 +209,13 @@ public abstract class Subscript extends RBuiltinNode { @SuppressWarnings("unused") @Specialization(guards = "indexes.isEmpty()") protected Object getNoInd(Object x, RArgsValuesAndNames indexes, RAbstractLogicalVector exact, RAbstractLogicalVector drop) { - throw RError.error(this, RError.Message.NO_INDEX); + throw error(RError.Message.NO_INDEX); } @SuppressWarnings("unused") @Specialization protected Object get(Object x, RMissing indexes, RAbstractLogicalVector exact, RAbstractLogicalVector drop) { - throw RError.error(this, RError.Message.NO_INDEX); + throw error(RError.Message.NO_INDEX); } @Specialization(guards = "!indexes.isEmpty()") diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java index 82199ccb54e0f2d861beb07bba78376d41e3f74d..6d6a04e16b09ab36560a092af70c849b6dc5ba66 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java @@ -23,23 +23,21 @@ package com.oracle.truffle.r.nodes.builtin.base.infix; import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertIndex; -import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.profile; import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; import com.oracle.truffle.r.nodes.access.vector.ExtractListElement; import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.base.infix.ProfiledSpecialsUtilsFactory.ProfiledSubsetSpecial2NodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.ProfiledSpecialsUtilsFactory.ProfiledSubsetSpecialNodeGen; import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertIndex; -import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ProfiledValue; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -84,13 +82,16 @@ abstract class SubsetSpecial extends SubscriptSpecialBase { @Cached("createAccess()") ExtractVectorNode extract) { return extract.apply(frame, vector, new Object[]{index}, RRuntime.LOGICAL_TRUE, RLogical.TRUE); } + + public static RNode create(boolean inReplacement, RNode vectorNode, ConvertIndex index) { + return ProfiledSubsetSpecialNodeGen.create(inReplacement, vectorNode, index); + } } /** * Subset special only handles single element integer/double index. In the case of list, we need to * create the actual list otherwise we just return the primitive type. */ -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) abstract class SubsetSpecial2 extends SubscriptSpecial2Base { @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create(); @@ -109,11 +110,14 @@ abstract class SubsetSpecial2 extends SubscriptSpecial2Base { @Cached("create()") ExtractListElement extract) { return RDataFactory.createList(new Object[]{extract.execute(vector, matrixIndex(vector, index1, index2))}); } + + public static RNode create(boolean inReplacement, RNode vectorNode, ConvertIndex index1, ConvertIndex index2) { + return ProfiledSubsetSpecial2NodeGen.create(inReplacement, vectorNode, index1, index2); + } } @RBuiltin(name = "[", kind = PRIMITIVE, parameterNames = {"x", "...", "drop"}, dispatch = INTERNAL_GENERIC, behavior = PURE) -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) -public abstract class Subset extends RBuiltinNode { +public abstract class Subset extends RBuiltinNode.Arg3 { @RBuiltin(name = ".subset", kind = PRIMITIVE, parameterNames = {"", "...", "drop"}, behavior = PURE) public abstract class DefaultBuiltin { @@ -122,12 +126,11 @@ public abstract class Subset extends RBuiltinNode { public static RNode special(ArgumentsSignature signature, RNode[] args, boolean inReplacement) { if (signature.getNonNullCount() == 0 && (args.length == 2 || args.length == 3)) { - ProfiledValue profiledVector = profile(args[0]); ConvertIndex index = convertIndex(args[1]); if (args.length == 2) { - return SubsetSpecialNodeGen.create(inReplacement, profiledVector, index); + return SubsetSpecial.create(inReplacement, args[0], index); } else { - return SubsetSpecial2NodeGen.create(inReplacement, profiledVector, index, convertIndex(args[2])); + return SubsetSpecial2.create(inReplacement, args[0], index, convertIndex(args[2])); } } return null; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java index 5376735712f03ae5cba2f47de923ae1cd46b0f78..14828d57c5abf1e0289ee25ddfb4148238b1cf4a 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java @@ -27,9 +27,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; @@ -50,8 +48,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; * argument is missing, i.e. {@code ~ x} result in {@code `~`(x)}. */ @RBuiltin(name = "~", kind = PRIMITIVE, parameterNames = {"x", "y"}, nonEvalArgs = {0, 1}, behavior = READS_FRAME) -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) -public abstract class Tilde extends RBuiltinNode { +public abstract class Tilde extends RBuiltinNode.Arg2 { private static final RStringVector FORMULA_CLASS = RDataFactory.createStringVectorFromScalar(RRuntime.FORMULA_CLASS); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java index d5ff59a1c998bf95082b0f30f173738d2e50f227..3d1e5f25835fc4646394354aa6611cd29187b945 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java @@ -32,10 +32,8 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode; import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; @@ -116,8 +114,7 @@ abstract class UpdateFieldSpecial extends SpecialsUtils.ListFieldSpecialBase { } @RBuiltin(name = "$<-", kind = PRIMITIVE, parameterNames = {"", "", "value"}, dispatch = INTERNAL_GENERIC, behavior = PURE) -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) -public abstract class UpdateField extends RBuiltinNode { +public abstract class UpdateField extends RBuiltinNode.Arg3 { @Child private ReplaceVectorNode update = ReplaceVectorNode.create(ElementAccessMode.FIELD_SUBSCRIPT, true); @Child private CastListNode castList; @@ -126,7 +123,7 @@ public abstract class UpdateField extends RBuiltinNode { static { Casts casts = new Casts(UpdateField.class); - casts.arg(1).defaultError(Message.INVALID_SUBSCRIPT).mustBe(stringValue(), RError.NO_CALLER, Message.INVALID_SUBSCRIPT_TYPE, Predef.typeName()).asStringVector().findFirst(); + casts.arg(1).defaultError(Message.INVALID_SUBSCRIPT).mustBe(stringValue(), Message.INVALID_SUBSCRIPT_TYPE, Predef.typeName()).asStringVector().findFirst(); } public static RNode createSpecial(ArgumentsSignature signature, RNode[] arguments, @SuppressWarnings("unused") boolean inReplacement) { @@ -145,7 +142,7 @@ public abstract class UpdateField extends RBuiltinNode { CompilerDirectives.transferToInterpreterAndInvalidate(); castList = insert(CastListNodeGen.create(true, true, false)); } - RError.warning(this, RError.Message.COERCING_LHS_TO_LIST); + warning(RError.Message.COERCING_LHS_TO_LIST); return castList.executeList(vector); } return vector; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java index cfc2f94db133139d1c2ff70524b496ab21a1b2ae..9bc4b7371cd0ea03c0fd97b882ca9b6dd3a0d928 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java @@ -23,7 +23,7 @@ package com.oracle.truffle.r.nodes.builtin.base.infix; import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertIndex; -import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.profile; +import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertValue; import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -31,21 +31,18 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import java.util.Arrays; import com.oracle.truffle.api.dsl.Fallback; -import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.base.infix.ProfiledSpecialsUtilsFactory.ProfiledUpdateSubscriptSpecial2NodeGen; +import com.oracle.truffle.r.nodes.builtin.base.infix.ProfiledSpecialsUtilsFactory.ProfiledUpdateSubscriptSpecialBaseNodeGen; import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertIndex; -import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ProfiledValue; +import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertValue; import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpecial2Common; import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpecialCommon; -import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; -import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -59,45 +56,38 @@ import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.ops.na.NACheck; -@NodeChild(value = "vector", type = ProfiledValue.class) -@NodeChild(value = "index", type = ConvertIndex.class) -@NodeChild(value = "value", type = RNode.class) abstract class UpdateSubscriptSpecial extends SubscriptSpecialCommon { protected UpdateSubscriptSpecial(boolean inReplacement) { super(inReplacement); } - @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false); - private final NACheck naCheck = NACheck.create(); - protected boolean simple(Object vector) { - return classHierarchy.execute(vector) == null; - } + protected abstract Object execute(VirtualFrame frame, Object vec, Object index, Object value); - @Specialization(guards = {"simple(vector)", "!vector.isShared()", "isValidIndex(vector, index)"}) + @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"}) protected RIntVector set(RIntVector vector, int index, int value) { return vector.updateDataAt(index - 1, value, naCheck); } - @Specialization(guards = {"simple(vector)", "!vector.isShared()", "isValidIndex(vector, index)"}) + @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"}) protected RDoubleVector set(RDoubleVector vector, int index, double value) { return vector.updateDataAt(index - 1, value, naCheck); } - @Specialization(guards = {"simple(vector)", "!vector.isShared()", "isValidIndex(vector, index)"}) + @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"}) protected RStringVector set(RStringVector vector, int index, String value) { return vector.updateDataAt(index - 1, value, naCheck); } - @Specialization(guards = {"simple(list)", "!list.isShared()", "isValidIndex(list, index)", "isSingleElement(value)"}) + @Specialization(guards = {"simpleVector(list)", "!list.isShared()", "isValidIndex(list, index)", "isSingleElement(value)"}) protected static Object set(RList list, int index, Object value) { list.setDataAt(list.getInternalStore(), index - 1, value); return list; } - @Specialization(guards = {"simple(vector)", "!vector.isShared()", "isValidIndex(vector, index)"}) + @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"}) protected RDoubleVector setDoubleIntIndexIntValue(RDoubleVector vector, int index, int value) { return vector.updateDataAt(index - 1, value, naCheck); } @@ -107,48 +97,44 @@ abstract class UpdateSubscriptSpecial extends SubscriptSpecialCommon { protected static Object setFallback(Object vector, Object index, Object value) { throw RSpecialFactory.throwFullCallNeeded(value); } + + public static RNode create(boolean inReplacement, RNode vector, ConvertIndex index, ConvertValue value) { + return ProfiledUpdateSubscriptSpecialBaseNodeGen.create(inReplacement, vector, index, value); + } } -@NodeChild(value = "vector", type = ProfiledValue.class) -@NodeChild(value = "index1", type = ConvertIndex.class) -@NodeChild(value = "index2", type = ConvertIndex.class) -@NodeChild(value = "value", type = RNode.class) abstract class UpdateSubscriptSpecial2 extends SubscriptSpecial2Common { protected UpdateSubscriptSpecial2(boolean inReplacement) { super(inReplacement); } - @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false); - private final NACheck naCheck = NACheck.create(); - protected boolean simple(Object vector) { - return classHierarchy.execute(vector) == null; - } + protected abstract Object execute(VirtualFrame frame, Object vec, Object index1, Object index2, Object value); - @Specialization(guards = {"simple(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"}) + @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"}) protected RIntVector set(RIntVector vector, int index1, int index2, int value) { return vector.updateDataAt(matrixIndex(vector, index1, index2), value, naCheck); } - @Specialization(guards = {"simple(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"}) + @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"}) protected RDoubleVector set(RDoubleVector vector, int index1, int index2, double value) { return vector.updateDataAt(matrixIndex(vector, index1, index2), value, naCheck); } - @Specialization(guards = {"simple(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"}) + @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"}) protected RStringVector set(RStringVector vector, int index1, int index2, String value) { return vector.updateDataAt(matrixIndex(vector, index1, index2), value, naCheck); } - @Specialization(guards = {"simple(list)", "!list.isShared()", "isValidIndex(list, index1, index2)", "isSingleElement(value)"}) + @Specialization(guards = {"simpleVector(list)", "!list.isShared()", "isValidIndex(list, index1, index2)", "isSingleElement(value)"}) protected Object set(RList list, int index1, int index2, Object value) { list.setDataAt(list.getInternalStore(), matrixIndex(list, index1, index2), value); return list; } - @Specialization(guards = {"simple(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"}) + @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"}) protected RDoubleVector setDoubleIntIndexIntValue(RDoubleVector vector, int index1, int index2, int value) { return vector.updateDataAt(matrixIndex(vector, index1, index2), value, naCheck); } @@ -158,11 +144,14 @@ abstract class UpdateSubscriptSpecial2 extends SubscriptSpecial2Common { protected static Object setFallback(Object vector, Object index1, Object index2, Object value) { throw RSpecialFactory.throwFullCallNeeded(value); } + + public static RNode create(boolean inReplacement, RNode vector, ConvertIndex index1, ConvertIndex index2, ConvertValue value) { + return ProfiledUpdateSubscriptSpecial2NodeGen.create(inReplacement, vector, index1, index2, value); + } } @RBuiltin(name = "[[<-", kind = PRIMITIVE, parameterNames = {"", "..."}, dispatch = INTERNAL_GENERIC, behavior = PURE) -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) -public abstract class UpdateSubscript extends RBuiltinNode { +public abstract class UpdateSubscript extends RBuiltinNode.Arg2 { @Child private ReplaceVectorNode replaceNode = ReplaceVectorNode.create(ElementAccessMode.SUBSCRIPT, false); @@ -174,12 +163,11 @@ public abstract class UpdateSubscript extends RBuiltinNode { public static RNode special(ArgumentsSignature signature, RNode[] args, boolean inReplacement) { if (SpecialsUtils.isCorrectUpdateSignature(signature) && (args.length == 3 || args.length == 4)) { - ProfiledValue vector = profile(args[0]); ConvertIndex index = convertIndex(args[1]); if (args.length == 3) { - return UpdateSubscriptSpecialNodeGen.create(inReplacement, vector, index, args[2]); + return UpdateSubscriptSpecial.create(inReplacement, args[0], index, convertValue(args[2])); } else { - return UpdateSubscriptSpecial2NodeGen.create(inReplacement, vector, index, convertIndex(args[2]), args[3]); + return UpdateSubscriptSpecial2.create(inReplacement, args[0], index, convertIndex(args[2]), convertValue(args[3])); } } return null; @@ -200,6 +188,6 @@ public abstract class UpdateSubscript extends RBuiltinNode { @Specialization(guards = "args.isEmpty()") @SuppressWarnings("unused") protected Object getNoInd(Object x, RArgsValuesAndNames args) { - throw RError.error(this, RError.Message.INVALID_ARG_NUMBER, "SubAssignArgs"); + throw error(RError.Message.INVALID_ARG_NUMBER, "SubAssignArgs"); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java index 30ad8a85fcf3cd07e9c6cafed84b6744df555820..bb734f4ae2ccc9815be1e4df37bb5aa08aa46c8f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java @@ -23,7 +23,7 @@ package com.oracle.truffle.r.nodes.builtin.base.infix; import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertIndex; -import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.profile; +import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertValue; import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -31,15 +31,12 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import java.util.Arrays; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertIndex; -import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ProfiledValue; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -47,9 +44,8 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.nodes.RNode; -@RBuiltin(name = "[<-", kind = PRIMITIVE, parameterNames = {"", "..."}, dispatch = INTERNAL_GENERIC, behavior = PURE) -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) -public abstract class UpdateSubset extends RBuiltinNode { +@RBuiltin(name = "[<-", kind = PRIMITIVE, parameterNames = {"..."}, dispatch = INTERNAL_GENERIC, behavior = PURE) +public abstract class UpdateSubset extends RBuiltinNode.Arg1 { @Child private ReplaceVectorNode replaceNode = ReplaceVectorNode.create(ElementAccessMode.SUBSET, false); private final ConditionProfile argsLengthLargerThanOneProfile = ConditionProfile.createBinaryProfile(); @@ -60,32 +56,37 @@ public abstract class UpdateSubset extends RBuiltinNode { public static RNode special(ArgumentsSignature signature, RNode[] args, boolean inReplacement) { if (SpecialsUtils.isCorrectUpdateSignature(signature) && (args.length == 3 || args.length == 4)) { - ProfiledValue vector = profile(args[0]); ConvertIndex index = convertIndex(args[1]); if (args.length == 3) { - return UpdateSubscriptSpecialNodeGen.create(inReplacement, vector, index, args[2]); + return UpdateSubscriptSpecial.create(inReplacement, args[0], index, convertValue(args[2])); } else { - return UpdateSubscriptSpecial2NodeGen.create(inReplacement, vector, index, convertIndex(args[2]), args[3]); + return UpdateSubscriptSpecial2.create(inReplacement, args[0], index, convertIndex(args[2]), convertValue(args[3])); } } return null; } - @Specialization(guards = "!args.isEmpty()") - protected Object update(VirtualFrame frame, Object x, RArgsValuesAndNames args) { + @Specialization(guards = "args.getLength() >= 2") + protected Object update(VirtualFrame frame, RArgsValuesAndNames args) { + // first argument: object to assign to + Object x = args.getArgument(0); + + // last argument: value to assign Object value = args.getArgument(args.getLength() - 1); + + // arguments between first and last are assumed to be indices Object[] pos; - if (argsLengthLargerThanOneProfile.profile(args.getLength() > 1)) { - pos = Arrays.copyOf(args.getArguments(), args.getLength() - 1); + if (argsLengthLargerThanOneProfile.profile(args.getLength() > 2)) { + pos = Arrays.copyOfRange(args.getArguments(), 1, args.getLength() - 1); } else { pos = new Object[]{RMissing.instance}; } return replaceNode.apply(frame, x, pos, value); } - @Specialization(guards = "args.isEmpty()") + @Specialization(guards = "args.getLength() < 2") @SuppressWarnings("unused") - protected Object getNoInd(Object x, RArgsValuesAndNames args) { - throw RError.error(this, RError.Message.INVALID_ARG_NUMBER, "SubAssignArgs"); + protected Object getNoInd(RArgsValuesAndNames args) { + throw error(RError.Message.INVALID_ARG_NUMBER, "SubAssignArgs"); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/WhileBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/WhileBuiltin.java index 9512dd07b558e46252f01859656fa879f34015c6..680ad83d25ad9c1a6c02c11ed5157d58fc4e1519 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/WhileBuiltin.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/WhileBuiltin.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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.builtin.base.infix; +import static com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts.noCasts; import static com.oracle.truffle.r.runtime.RVisibility.OFF; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -32,7 +33,11 @@ import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "while", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE) -public abstract class WhileBuiltin extends RBuiltinNode { +public abstract class WhileBuiltin extends RBuiltinNode.Arg1 { + static { + noCasts(WhileBuiltin.class); + } + @SuppressWarnings("unused") @Specialization protected Object doIt(Object x) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AttributesPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AttributesPrinter.java index 785cf3c27351237d39f0f91cd62ea00901050e91..0f7201f09f7d2a53c3fb51bfd9af113579101cde 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AttributesPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AttributesPrinter.java @@ -17,6 +17,7 @@ import java.io.PrintWriter; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.object.DynamicObject; +import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RAttributable; @@ -62,7 +63,7 @@ final class AttributesPrinter implements ValuePrinter<RAttributable> { continue; } } - if (value.hasClass(RRuntime.CLASS_DATA_FRAME)) { + if (ClassHierarchyNode.hasClass(value, RRuntime.CLASS_DATA_FRAME)) { if (RRuntime.ROWNAMES_ATTR_KEY.equals(a.getName())) { continue; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java index 8181e251d47ba78d1833ad929d41922146e86163..635ec096266e654196e0ba316bf4b1b073197384 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java @@ -58,7 +58,7 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe @Override protected void printElement(int i, FormatMetrics fm) throws IOException { ComplexVectorMetrics cfm = (ComplexVectorMetrics) fm; - String v = encodeComplex(vector.getDataAt(i), cfm, printCtx.parameters()); + String v = encodeComplex(vector.getDataAt(i), cfm, '.', printCtx.parameters()); out.print(v); } @@ -401,20 +401,20 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe @TruffleBoundary public static String encodeComplex(RComplex x, int digits, int sciPen, String naString) { ComplexVectorMetrics cvm = formatComplexVector(x, 0, 1, 0, digits, sciPen, naString.length()); - return encodeComplex(x, cvm, digits, naString); + return encodeComplex(x, cvm, '.', digits, naString); } @TruffleBoundary - static String encodeComplex(RComplex x, ComplexVectorMetrics cvm, PrintParameters pp) { - return encodeComplex(x, cvm, pp.getDigits(), pp.getNaString()); + static String encodeComplex(RComplex x, ComplexVectorMetrics cvm, char cdec, PrintParameters pp) { + return encodeComplex(x, cvm, cdec, pp.getDigits(), pp.getNaString()); } @TruffleBoundary - static String encodeComplex(RComplex x, ComplexVectorMetrics cvm, int digits, String naString) { + static String encodeComplex(RComplex x, ComplexVectorMetrics cvm, char cdec, int digits, String naString) { if (x.isNA()) { - return DoubleVectorPrinter.encodeReal(RRuntime.DOUBLE_NA, cvm.maxWidth, 0, 0, '.', naString); + return DoubleVectorPrinter.encodeReal(RRuntime.DOUBLE_NA, cvm.maxWidth, 0, 0, cdec, naString); } else { - String s = encodeComplex(x, cvm.wr, cvm.dr, cvm.er, cvm.wi, cvm.di, cvm.ei, '.', digits, naString); + String s = encodeComplex(x, cvm.wr, cvm.dr, cvm.er, cvm.wi, cvm.di, cvm.ei, cdec, digits, naString); int g = cvm.maxWidth - cvm.wr - cvm.wi - 2; if (g > 0) { // fill the remaining space by blanks to fit the maxWidth @@ -475,4 +475,15 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe } return buff; } + + public static String[] format(RAbstractComplexVector value, boolean trim, int nsmall, int width, char decimalMark, PrintParameters pp) { + ComplexVectorMetrics dfm = formatComplexVector(value, 0, value.getLength(), nsmall, pp); + ComplexVectorMetrics adjusted = new ComplexVectorMetrics(Math.max(trim ? 1 : dfm.wr, width), dfm.dr, dfm.er, Math.max(trim ? 1 : dfm.wi, width), dfm.di, dfm.ei); + + String[] result = new String[value.getLength()]; + for (int i = 0; i < value.getLength(); i++) { + result[i] = encodeComplex(value.getDataAt(i), adjusted, decimalMark, pp); + } + return result; + } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java index ac9c3b375ceb2816c1e32e8ec8913255f9e45d81..9ee413f6e6f9a50696f92847f6361c4628c1038d 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java @@ -5,7 +5,7 @@ * * Copyright (c) 1995, 1996 Robert Gentleman and Ross Ihaka * Copyright (c) 1997-2013, The R Core Team - * Copyright (c) 2016, Oracle and/or its affiliates + * Copyright (c) 2016, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -77,7 +77,7 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect } @TruffleBoundary - static DoubleVectorMetrics formatDoubleVector(RAbstractDoubleVector x, int offs, int n, int nsmall, int digits, int sciPen, int naWidth) { + public static DoubleVectorMetrics formatDoubleVector(RAbstractDoubleVector x, int offs, int n, int nsmall, int digits, int sciPen, int naWidth) { int left; int right; int sleft; @@ -406,7 +406,18 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect return prependBlanks(w, id); } else if (e != 0) { String fmt = String.format((d != 0) ? "%%#%d.%de" : "%%%d.%de", Math.min(w, (NB - 1)), d); - return snprintf(NB, fmt, x).replace('.', cdec); + String result; + if (Math.abs(x) < 1e-300 && Math.abs(x) >= Double.MIN_VALUE) { + // work around java formatting bug for small numbers like 1.53160350210786e-322 + result = snprintf(NB, fmt, x * 1e100); + StringBuilder str = new StringBuilder(result); + assert str.charAt(str.length() - 3) == '2'; + str.setCharAt(str.length() - 3, '3'); + result = str.toString(); + } else { + result = snprintf(NB, fmt, x); + } + return result.replace('.', cdec); } else { /* e = 0 */ DecimalFormat df = null; if (d < CACHED_FORMATS.length) { @@ -427,8 +438,7 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect } private static String prependBlanks(int width, String id) { - assert id.length() <= width; - if (id.length() == width) { + if (id.length() >= width) { return id; } StringBuilder str = new StringBuilder(width); @@ -437,4 +447,15 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect } return str.append(id).toString(); } + + public static String[] format(RAbstractDoubleVector value, boolean trim, int nsmall, int width, char decimalMark, PrintParameters pp) { + DoubleVectorMetrics dfm = formatDoubleVector(value, 0, value.getLength(), nsmall, pp); + int w = Math.max(trim ? 1 : dfm.maxWidth, width); + + String[] result = new String[value.getLength()]; + for (int i = 0; i < value.getLength(); i++) { + result[i] = encodeReal(value.getDataAt(i), w, dfm.d, dfm.e, decimalMark, pp); + } + return result; + } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java index 726492384f3032d8fcf758b706942003e58e22b8..5453a2fa40ab27cf826ab8da4ca2a6f58cda10b8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java @@ -5,7 +5,7 @@ * * Copyright (c) 1995, 1996 Robert Gentleman and Ross Ihaka * Copyright (c) 1997-2013, The R Core Team - * Copyright (c) 2016, Oracle and/or its affiliates + * Copyright (c) 2016, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -20,7 +20,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; //Transcribed from GnuR, src/main/printutils.c, src/main/format.c -final class IntegerVectorPrinter extends VectorPrinter<RAbstractIntVector> { +public final class IntegerVectorPrinter extends VectorPrinter<RAbstractIntVector> { static final IntegerVectorPrinter INSTANCE = new IntegerVectorPrinter(); @@ -66,7 +66,7 @@ final class IntegerVectorPrinter extends VectorPrinter<RAbstractIntVector> { } } - static FormatMetrics formatIntVector(RAbstractIntVector x, int offs, int n, int naWidth) { + public static FormatMetrics formatIntVector(RAbstractIntVector x, int offs, int n, int naWidth) { int xmin = RRuntime.INT_MAX_VALUE; int xmax = RRuntime.INT_MIN_VALUE; boolean naflag = false; @@ -114,11 +114,28 @@ final class IntegerVectorPrinter extends VectorPrinter<RAbstractIntVector> { */ static int NB = 1000; - static String encodeInteger(int x, int w, PrintParameters pp) { + public static String encodeInteger(int x, int w, PrintParameters pp) { if (x == RRuntime.INT_NA) { return Utils.snprintf(NB, "%" + Utils.asBlankArg(Math.min(w, (NB - 1))) + "s", pp.getNaString()); } else { return Utils.snprintf(NB, "%" + Utils.asBlankArg(Math.min(w, (NB - 1))) + "d", x); } } + + public static String[] format(RAbstractIntVector value, boolean trim, int width, PrintParameters pp) { + int w; + if (trim) { + w = 1; + } else { + FormatMetrics metrics = formatIntVector(value, 0, value.getLength(), pp.getNaWidth()); + w = metrics.maxWidth; + } + w = Math.max(w, width); + + String[] result = new String[value.getLength()]; + for (int i = 0; i < value.getLength(); i++) { + result[i] = encodeInteger(value.getDataAt(i), w, pp); + } + return result; + } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java index e0915c3817a13782ed7cb185ede7219c3ddad633..3cde3e059f0377c95c9090efa054f8b38b05f3e0 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java @@ -79,33 +79,30 @@ final class ListPrinter extends AbstractValuePrinter<RAbstractListVector> { RAbstractLogicalVector lv = (RAbstractLogicalVector) tmp; if (lv.getLength() == 1) { FormatMetrics fm = LogicalVectorPrinter.formatLogicalVector(lv, 0, 1, pp.getNaWidth()); - pbuf = snprintf(115, "%s", - LogicalVectorPrinter.encodeLogical(lv.getDataAt(0), fm.maxWidth, pp)); + pbuf = LogicalVectorPrinter.encodeLogical(lv.getDataAt(0), fm.maxWidth, pp); } else { - pbuf = snprintf(115, "Logical,%d", lv.getLength()); + pbuf = "Logical," + lv.getLength(); } } else if (tmp instanceof RAbstractIntVector) { RAbstractIntVector iv = (RAbstractIntVector) tmp; if (printCtx.printerNode().inherits(iv, RRuntime.CLASS_FACTOR)) { /* factors are stored as integers */ - pbuf = snprintf(115, "factor,%d", iv.getLength()); + pbuf = "factor," + iv.getLength(); } else { if (iv.getLength() == 1) { FormatMetrics fm = IntegerVectorPrinter.formatIntVector(iv, 0, 1, pp.getNaWidth()); - pbuf = snprintf(115, "%s", - IntegerVectorPrinter.encodeInteger(iv.getDataAt(0), fm.maxWidth, pp)); + pbuf = IntegerVectorPrinter.encodeInteger(iv.getDataAt(0), fm.maxWidth, pp); } else { - pbuf = snprintf(115, "Integer,%d", iv.getLength()); + pbuf = "Integer," + iv.getLength(); } } } else if (tmp instanceof RAbstractDoubleVector) { RAbstractDoubleVector dv = (RAbstractDoubleVector) tmp; if (dv.getLength() == 1) { DoubleVectorMetrics fm = DoubleVectorPrinter.formatDoubleVector(dv, 0, 1, 0, pp); - pbuf = snprintf(115, "%s", - DoubleVectorPrinter.encodeReal(dv.getDataAt(0), fm, pp)); + pbuf = DoubleVectorPrinter.encodeReal(dv.getDataAt(0), fm, pp); } else { - pbuf = snprintf(115, "Numeric,%d", dv.getLength()); + pbuf = "Numeric," + dv.getLength(); } } else if (tmp instanceof RAbstractComplexVector) { RAbstractComplexVector cv = (RAbstractComplexVector) tmp; @@ -113,36 +110,35 @@ final class ListPrinter extends AbstractValuePrinter<RAbstractListVector> { RComplex x = cv.getDataAt(0); if (RRuntime.isNA(x.getRealPart()) || RRuntime.isNA(x.getImaginaryPart())) { /* formatReal(NA) --> w=R_print.na_width, d=0, e=0 */ - pbuf = snprintf(115, "%s", - DoubleVectorPrinter.encodeReal(RRuntime.DOUBLE_NA, pp.getNaWidth(), 0, 0, '.', pp)); + pbuf = DoubleVectorPrinter.encodeReal(RRuntime.DOUBLE_NA, pp.getNaWidth(), 0, 0, '.', pp); } else { ComplexVectorMetrics cvm = ComplexVectorPrinter.formatComplexVector(x, 0, 1, 0, pp); - pbuf = snprintf(115, "%s", ComplexVectorPrinter.encodeComplex(x, cvm, pp)); + pbuf = ComplexVectorPrinter.encodeComplex(x, cvm, '.', pp); } } else { - pbuf = snprintf(115, "Complex,%d", cv.getLength()); + pbuf = "Complex," + cv.getLength(); } } else if (tmp instanceof RAbstractStringVector) { RAbstractStringVector sv = (RAbstractStringVector) tmp; if (sv.getLength() == 1) { - String ctmp = sv.getDataAt(0); + String ctmp = RRuntime.escapeString(sv.getDataAt(0), true, true); int len = ctmp.length(); if (len < 100) { - pbuf = snprintf(115, "\"%s\"", ctmp); + pbuf = ctmp; } else { - pbuf = snprintf(101, "\"%s", ctmp) + "\" [truncated]"; + pbuf = Utils.trimSize(101, ctmp) + "\" [truncated]"; } } else { - pbuf = snprintf(115, "Character,%d", sv.getLength()); + pbuf = "Character," + sv.getLength(); } } else if (tmp instanceof RAbstractRawVector) { - pbuf = snprintf(115, "Raw,%d", ((RAbstractRawVector) (tmp)).getLength()); + pbuf = "Raw," + ((RAbstractRawVector) (tmp)).getLength(); } else if (tmp instanceof RAbstractListVector) { - pbuf = snprintf(115, "List,%d", ((RAbstractListVector) (tmp)).getLength()); + pbuf = "List," + ((RAbstractListVector) (tmp)).getLength(); } else if (tmp instanceof RLanguage) { - pbuf = snprintf(115, "Expression"); + pbuf = "Expression"; } else { - pbuf = snprintf(115, "?"); + pbuf = "?"; } t[i] = pbuf; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java index 5e0272f34c18817e30b2cd9b480237ffd66039d0..29231624992cce41ae975e5c03bbc1b88038f6fa 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java @@ -5,7 +5,7 @@ * * Copyright (c) 1995, 1996 Robert Gentleman and Ross Ihaka * Copyright (c) 1997-2013, The R Core Team - * Copyright (c) 2016, Oracle and/or its affiliates + * Copyright (c) 2016, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -21,7 +21,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; //Transcribed from GnuR, src/main/printutils.c, src/main/format.c -final class LogicalVectorPrinter extends VectorPrinter<RAbstractLogicalVector> { +public final class LogicalVectorPrinter extends VectorPrinter<RAbstractLogicalVector> { static final LogicalVectorPrinter INSTANCE = new LogicalVectorPrinter(); @@ -96,4 +96,21 @@ final class LogicalVectorPrinter extends VectorPrinter<RAbstractLogicalVector> { return snprintf(NB, fmt, "FALSE"); } } + + public static String[] format(RAbstractLogicalVector value, boolean trim, int width, PrintParameters pp) { + int w; + if (trim) { + w = 1; + } else { + FormatMetrics metrics = formatLogicalVector(value, 0, value.getLength(), pp.getNaWidth()); + w = metrics.maxWidth; + } + w = Math.max(w, width); + + String[] result = new String[value.getLength()]; + for (int i = 0; i < value.getLength(); i++) { + result[i] = encodeLogical(value.getDataAt(i), w, pp); + } + return result; + } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java index 5927ddf98ec477d3b0d8c3dc191785040e0831f2..8d357469522dcb9584c6a379ea3c8517efa14423 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java @@ -5,14 +5,12 @@ * * Copyright (c) 1995, 1996 Robert Gentleman and Ross Ihaka * Copyright (c) 1997-2013, The R Core Team - * Copyright (c) 2016, Oracle and/or its affiliates + * Copyright (c) 2016, 2017, Oracle and/or its affiliates * * All rights reserved. */ package com.oracle.truffle.r.nodes.builtin.base.printer; -import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.snprintf; - import java.io.IOException; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -57,23 +55,23 @@ final class PairListPrinter extends AbstractValuePrinter<RPairList> { if (tmp == null || tmp == RNull.instance) { pbuf = RRuntime.NULL; } else if (tmp instanceof RAbstractLogicalVector) { - pbuf = snprintf(115, "Logical,%d", ((RAbstractContainer) tmp).getLength()); + pbuf = "Logical," + ((RAbstractContainer) tmp).getLength(); } else if (tmp instanceof RAbstractIntVector) { - pbuf = snprintf(115, "Integer,%d", ((RAbstractContainer) tmp).getLength()); + pbuf = "Integer," + ((RAbstractContainer) tmp).getLength(); } else if (tmp instanceof RAbstractDoubleVector) { - pbuf = snprintf(115, "Numeric,%d", ((RAbstractContainer) tmp).getLength()); + pbuf = "Numeric," + ((RAbstractContainer) tmp).getLength(); } else if (tmp instanceof RAbstractComplexVector) { - pbuf = snprintf(115, "Complex,%d", ((RAbstractContainer) tmp).getLength()); + pbuf = "Complex," + ((RAbstractContainer) tmp).getLength(); } else if (tmp instanceof RAbstractStringVector) { - pbuf = snprintf(115, "Character,%d", ((RAbstractContainer) tmp).getLength()); + pbuf = "Character," + ((RAbstractContainer) tmp).getLength(); } else if (tmp instanceof RAbstractRawVector) { - pbuf = snprintf(115, "Raw,%d", ((RAbstractContainer) tmp).getLength()); + pbuf = "Raw," + ((RAbstractContainer) tmp).getLength(); } else if (tmp instanceof RAbstractListVector) { - pbuf = snprintf(115, "List,%d", ((RAbstractContainer) tmp).getLength()); + pbuf = "List," + ((RAbstractContainer) tmp).getLength(); } else if (tmp instanceof RLanguage) { - pbuf = snprintf(115, "Expression"); + pbuf = "Expression"; } else { - pbuf = snprintf(115, "?"); + pbuf = "?"; } t[i] = pbuf; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java index 27deabed40d5cdf104b616f879fe99d9f7348c85..45a9a4724b7fe11f0944cb97c36d72174976e2a8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java @@ -5,7 +5,7 @@ * * Copyright (c) 1995, 1996 Robert Gentleman and Ross Ihaka * Copyright (c) 1997-2013, The R Core Team - * Copyright (c) 2016, Oracle and/or its affiliates + * Copyright (c) 2016, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -21,7 +21,6 @@ import com.oracle.truffle.r.nodes.builtin.base.Format; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RString; public final class PrintParameters { @CompilationFinal private static int DefaultDigits = -1; @@ -58,8 +57,7 @@ public final class PrintParameters { } @TruffleBoundary - PrintParameters(Object digits, boolean quote, Object naPrint, - Object printGap, boolean right, Object max, boolean useSource, @SuppressWarnings("unused") boolean noOpt) { + PrintParameters(Object digits, boolean quote, Object naPrint, Object printGap, boolean right, Object max, boolean useSource, @SuppressWarnings("unused") boolean noOpt) { setDefaults(); @@ -79,12 +77,12 @@ public final class PrintParameters { // condition, the GnuR application ignores that condition. It was revealed when running // test com.oracle.truffle.r.test.builtins.TestBuiltin_printdefault, which fails if the // condition is present complaining about an invalid na.print specification. - // if (!(naPrint instanceof RString) || ((RString) naPrint).getValue().length() < 1) + // if (!(naPrint instanceof String) || ((String) naPrint).getValue().length() < 1) // throw new // IllegalArgumentException(String.format("invalid 'na.print' specification")); - String nav = naPrint.toString(); - if (!"".equals(nav)) { - this.naString = this.naStringNoquote = ((RString) naPrint).getValue(); + String nav = (String) naPrint; + if (!nav.isEmpty()) { + this.naString = this.naStringNoquote = nav; this.naWidth = this.naWidthNoquote = this.naString.length(); } } @@ -141,7 +139,7 @@ public final class PrintParameters { } public void setDefaults() { - this.naString = RRuntime.STRING_NA; + this.naString = "NA"; this.naStringNoquote = "<NA>"; this.naWidth = this.naString.length(); this.naWidthNoquote = this.naStringNoquote.length(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringVectorPrinter.java index 7d6228c262720c6cbd4770b3bee4499ec2e09992..5ba2ea9ebc1e0f52b2601b313cda108089ada5a4 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringVectorPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringVectorPrinter.java @@ -5,7 +5,7 @@ * * Copyright (c) 1995, 1996 Robert Gentleman and Ross Ihaka * Copyright (c) 1997-2013, The R Core Team - * Copyright (c) 2016, Oracle and/or its affiliates + * Copyright (c) 2016, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -104,7 +104,7 @@ final class StringVectorPrinter extends VectorPrinter<RAbstractStringVector> { for (int i = 0; i < n; i++) { String s = x.getDataAt(offs + i); - String xi = quote ? RRuntime.quoteString(s, false) : s; + String xi = RRuntime.escapeString(s, false, quote); if (xi == RRuntime.STRING_NA) { l = quote ? pp.getNaWidth() : pp.getNaWidthNoquote(); @@ -167,20 +167,11 @@ final class StringVectorPrinter extends VectorPrinter<RAbstractStringVector> { } static String encode(String value, int w, PrintParameters pp) { - final boolean quote = pp.getQuote(); - final String s; - if (quote) { - if (RRuntime.isNA(value)) { - s = pp.getNaString(); - } else { - s = RRuntime.quoteString(value, false); - } + String s; + if (RRuntime.isNA(value)) { + s = pp.getQuote() ? pp.getNaString() : pp.getNaStringNoquote(); } else { - if (RRuntime.isNA(value)) { - s = pp.getNaStringNoquote(); - } else { - s = value; - } + s = RRuntime.escapeString(value, false, pp.getQuote()); } return StringVectorPrinter.encode(s, w, pp.getRight() ? PrintJustification.right : PrintJustification.left); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/Utils.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/Utils.java index 62e5a9c52f0194467a6e7d5dc62562e11e05e353..5c3a70f0561d0a22e6d1ff3a18b8078ef3483450 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/Utils.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/Utils.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 @@ -36,6 +36,10 @@ final class Utils { return fs.length() <= size ? fs : fs.substring(0, size); } + public static String trimSize(int size, String value) { + return value.length() <= size ? value : value.substring(0, size); + } + public static String asBlankArg(int blanks) { return blanks == 0 ? "" : blanks + ""; } 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 458380020c8600ab1b9889bcb97cbf7592f85f23..6beeea072ece55a1284ae5c7f54a4f8d4131a51b 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 @@ -63,7 +63,6 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RLogicalVector; -import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.data.RVector; @@ -130,12 +129,7 @@ public final class ValuePrinterNode extends RBaseNode { } catch (UnknownIdentifierException | UnsupportedMessageException e) { throw RInternalError.shouldNotReachHere(e); } - return (String) value; - } - - @Override - public RStringVector getImplicitClass() { - return RStringVector.implicitClassHeader; + return String.valueOf(value); } @Override @@ -149,6 +143,7 @@ public final class ValuePrinterNode extends RBaseNode { boolean allBoolean = true; boolean allInteger = true; boolean allNumber = true; + boolean allCharacter = true; boolean allString = true; for (int i = 0; i < size; i++) { Object value = ForeignAccess.sendRead(readNode, obj, i); @@ -158,6 +153,7 @@ public final class ValuePrinterNode extends RBaseNode { allBoolean &= value instanceof Boolean; allInteger &= value instanceof Integer; allNumber &= value instanceof Number; + allCharacter &= value instanceof Character; allString &= value instanceof String; } if (allBoolean) { @@ -186,11 +182,6 @@ public final class ValuePrinterNode extends RBaseNode { return RRuntime.asLogical((Boolean) value); } - @Override - public RStringVector getImplicitClass() { - return RIntVector.implicitClassHeader; - } - @Override public RLogicalVector materialize() { throw RInternalError.shouldNotReachHere(); @@ -223,11 +214,6 @@ public final class ValuePrinterNode extends RBaseNode { return (Integer) value; } - @Override - public RStringVector getImplicitClass() { - return RIntVector.implicitClassHeader; - } - @Override public RIntVector materialize() { throw RInternalError.shouldNotReachHere(); @@ -260,18 +246,13 @@ public final class ValuePrinterNode extends RBaseNode { return ((Number) value).doubleValue(); } - @Override - public RStringVector getImplicitClass() { - return RDoubleVector.implicitClassHeader; - } - @Override public RDoubleVector materialize() { throw RInternalError.shouldNotReachHere(); } } return new RDoubleWrapper(size); - } else if (allString) { + } else if (allString || allCharacter) { return new RStringWrapper(size, obj); } else { class RListWrapper extends TruffleObjectWrapper implements RAbstractListVector { @@ -299,11 +280,6 @@ public final class ValuePrinterNode extends RBaseNode { return value; } - @Override - public RStringVector getImplicitClass() { - return RList.implicitClassHeader; - } - @Override public RList materialize() { throw RInternalError.shouldNotReachHere(); @@ -349,11 +325,6 @@ public final class ValuePrinterNode extends RBaseNode { return value; } - @Override - public RStringVector getImplicitClass() { - return RList.implicitClassHeader; - } - @Override public RStringVector getNames() { return names; @@ -515,21 +486,11 @@ public final class ValuePrinterNode extends RBaseNode { throw RInternalError.shouldNotReachHere(); } - @Override - public Class<?> getElementClass() { - throw RInternalError.shouldNotReachHere(); - } - @Override public RTypedValue getNonShared() { throw RInternalError.shouldNotReachHere(); } - @Override - public RShareable materializeToShareable() { - throw RInternalError.shouldNotReachHere(); - } - @Override public RStringVector getNames() { return null; @@ -560,11 +521,6 @@ public final class ValuePrinterNode extends RBaseNode { throw RInternalError.shouldNotReachHere(); } - @Override - public RStringVector getImplicitClass() { - return null; - } - @Override public RType getRType() { return RType.Integer; @@ -608,6 +564,7 @@ public final class ValuePrinterNode extends RBaseNode { 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/base/printer/ValuePrinters.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java index dfa54ca7918858defa742bee17d5b510b23d9433..0bd88751d6643cdb10f595f18ad40e3a5b98507f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java @@ -28,12 +28,14 @@ import java.util.Map; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RExpression; import com.oracle.truffle.r.runtime.data.RExternalPtr; import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RInteropScalar; import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPairList; @@ -74,7 +76,7 @@ final class ValuePrinters implements ValuePrinter<Object> { if (v == RNull.instance) { NullPrinter.INSTANCE.print(null, printCtx); } else { - // handle types that can appear via Truffle interop + // handle types that are meant for or can appear via Truffle interop Object x = v; if (x instanceof Boolean) { x = RRuntime.asLogical((Boolean) x); @@ -82,6 +84,8 @@ final class ValuePrinters implements ValuePrinter<Object> { x = ((Number) x).doubleValue(); } else if (x instanceof Character) { x = ((Character) x).toString(); + } else if (x instanceof RInteropScalar) { + x = ((RInteropScalar) x).getRValue(); } // try to box a scalar primitive value to the respective vector x = printCtx.printerNode().boxPrimitive(x); @@ -118,7 +122,7 @@ final class ValuePrinters implements ValuePrinter<Object> { @TruffleBoundary private static boolean hasClass(Object x) { - return ((RAttributable) x).hasClass(RRuntime.CLASS_FACTOR); + return ClassHierarchyNode.hasClass((RAttributable) x, RRuntime.CLASS_FACTOR); } public static void printNewLine(PrintContext printCtx) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java index 8d22e642dc0c79fe3ba570a2051ec08446a1c659..611ee0d6eae2e000a2f3ef45a855f3e740a1f942 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java @@ -262,10 +262,10 @@ abstract class VectorPrinter<T extends RAbstractVector> extends AbstractValuePri /* PR#850 */ if (rl != null && r > rl.getLength()) { - throw RError.error(printCtx.printerNode(), RError.Message.GENERIC, "too few row labels"); + throw printCtx.printerNode().error(RError.Message.GENERIC, "too few row labels"); } if (cl != null && c > cl.getLength()) { - throw RError.error(printCtx.printerNode(), RError.Message.GENERIC, "too few column labels"); + throw printCtx.printerNode().error(RError.Message.GENERIC, "too few column labels"); } if (r == 0 && c == 0) { // FIXME? names(dimnames(.)) : out.print("<0 x 0 matrix>"); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/ContextSystemFunctionFactory.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/ContextSystemFunctionFactory.java index a65602428e16c18ff456d1962ae2c505078b4be6..cfb7d5c70ae05cad44e312fce61f577d0eeb8888 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/ContextSystemFunctionFactory.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/ContextSystemFunctionFactory.java @@ -59,7 +59,7 @@ public class ContextSystemFunctionFactory extends SystemFunctionFactory { @Specialization protected Object systemFunction(VirtualFrame frame, RAbstractStringVector args, RAbstractStringVector env, boolean intern) { initContextRNode(); - Object result = contextRNode.executeBuiltin(frame, args, env, intern); + Object result = contextRNode.execute(frame, args, env, intern); return result; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunction.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunction.java index ad08dd85ae9969918a2a38814598b27c7698c74c..3fbbfa50905c650e08e36cb383b340948cfc3085 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunction.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunction.java @@ -36,13 +36,13 @@ import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = "system", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"command", "intern"}, behavior = COMPLEX) -public abstract class SystemFunction extends RBuiltinNode { +public abstract class SystemFunction extends RBuiltinNode.Arg2 { @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); static { Casts casts = new Casts(SystemFunction.class); casts.arg("command").mustBe(stringValue(), RError.Message.SYSTEM_CHAR_ARG).asStringVector().findFirst(); - casts.arg("intern").asLogicalVector().findFirst().notNA(RError.Message.SYSTEM_INTERN_NOT_NA).map(toBoolean()); + casts.arg("intern").asLogicalVector().findFirst().mustNotBeNA(RError.Message.SYSTEM_INTERN_NOT_NA).map(toBoolean()); } @Specialization 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 2b3370bbb83ffad321c38ec351176d4413261ab8..c59f4dbc43c325a0046106d0e04140d1123b77f4 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 @@ -23,7 +23,6 @@ package com.oracle.truffle.r.nodes.builtin.fastr; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.equalTo; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gt; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement; @@ -36,9 +35,13 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.java.JavaInterop; import com.oracle.truffle.api.vm.PolyglotEngine; import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.RChannel; import com.oracle.truffle.r.runtime.RCmdOptions.Client; import com.oracle.truffle.r.runtime.RError; @@ -47,6 +50,8 @@ import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.context.ContextInfo; import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.context.RContext.ContextKind; +import com.oracle.truffle.r.runtime.context.RContext.EvalThread; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RList; @@ -54,6 +59,7 @@ import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.env.REnvironment; /** * The FastR builtins that allow multiple "virtual" R sessions potentially executing in parallel. @@ -66,12 +72,9 @@ public class FastRContext { } private static void kind(Casts casts) { - casts.arg("kind").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().notNA().mustBe( - equalTo(RContext.ContextKind.SHARE_NOTHING.name()).or(equalTo(RContext.ContextKind.SHARE_PARENT_RW.name()).or(equalTo(RContext.ContextKind.SHARE_PARENT_RO.name())))); - } - - private static void pc(Casts casts) { - casts.arg("pc").asIntegerVector().findFirst().notNA().mustBe(gt(0)); + casts.arg("kind").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().mustNotBeNA().mustBe( + equalTo(RContext.ContextKind.SHARE_NOTHING.name()).or(equalTo(RContext.ContextKind.SHARE_PARENT_RW.name()).or( + equalTo(RContext.ContextKind.SHARE_PARENT_RO.name()).or(equalTo(RContext.ContextKind.SHARE_ALL.name()))))); } private static void key(Casts casts) { @@ -84,11 +87,22 @@ public class FastRContext { } @RBuiltin(name = ".fastr.context.get", kind = PRIMITIVE, parameterNames = {}, behavior = READS_STATE) - public abstract static class Get extends RBuiltinNode { + public abstract static class Get extends RBuiltinNode.Arg0 { @Specialization @TruffleBoundary - protected Object get() { - return RContext.getInstance(); + protected TruffleObject get() { + return JavaInterop.asTruffleObject(RContext.getInstance()); + } + } + + 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)) { + ContextInfo.resetMultiSlotIndexGenerator(); + } else { + throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, "Shared contexts can be created only if no other child contexts exist"); + } } } @@ -98,40 +112,51 @@ public class FastRContext { * {@code .fastr.context.join}. * */ - @RBuiltin(name = ".fastr.context.spawn", kind = PRIMITIVE, parameterNames = {"exprs", "pc", "kind"}, behavior = COMPLEX) - public abstract static class Spawn extends RBuiltinNode { + @RBuiltin(name = ".fastr.context.spawn", kind = PRIMITIVE, parameterNames = {"exprs", "kind"}, behavior = COMPLEX) + public abstract static class Spawn extends RBuiltinNode.Arg2 { @Override public Object[] getDefaultParameterValues() { - return new Object[]{RMissing.instance, 1, "SHARE_NOTHING"}; + return new Object[]{RMissing.instance, FastROptions.SharedContexts.getBooleanValue() ? "SHARE_ALL" : "SHARE_NOTHING"}; } static { Casts casts = new Casts(Spawn.class); CastsHelper.exprs(casts); - CastsHelper.pc(casts); CastsHelper.kind(casts); } @Specialization @TruffleBoundary - protected RIntVector spawn(RAbstractStringVector exprs, int pc, String kind) { + protected RIntVector spawn(RAbstractStringVector exprs, String kind) { RContext.ContextKind contextKind = RContext.ContextKind.valueOf(kind); - RContext.EvalThread[] threads = new RContext.EvalThread[pc]; - int[] data = new int[pc]; - for (int i = 0; i < pc; i++) { + if (FastROptions.SharedContexts.getBooleanValue() && contextKind != ContextKind.SHARE_ALL) { + throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, "Only shared contexts are allowed"); + } + handleSharedContexts(contextKind); + + int length = exprs.getLength(); + RContext.EvalThread[] threads = new RContext.EvalThread[length]; + int[] data = new int[length]; + for (int i = 0; i < length; i++) { ContextInfo info = createContextInfo(contextKind); - threads[i] = new RContext.EvalThread(info, RSource.fromTextInternal(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL)); + threads[i] = new RContext.EvalThread(info, RSource.fromTextInternalInvisible(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL)); data[i] = info.getId(); } - for (int i = 0; i < pc; i++) { + if (contextKind == ContextKind.SHARE_ALL) { + REnvironment.convertSearchpathToMultiSlot(); + } + for (int i = 0; i < length; i++) { threads[i].start(); } + for (int i = 0; i < length; i++) { + threads[i].waitForInit(); + } return RDataFactory.createIntVector(data, RDataFactory.COMPLETE_VECTOR); } } @RBuiltin(name = ".fastr.context.join", visibility = OFF, kind = PRIMITIVE, parameterNames = {"handle"}, behavior = COMPLEX) - public abstract static class Join extends RBuiltinNode { + public abstract static class Join extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(Join.class); @@ -152,7 +177,7 @@ public class FastRContext { } } } catch (InterruptedException ex) { - throw RError.error(this, RError.Message.GENERIC, "error finishing eval thread"); + throw error(RError.Message.GENERIC, "error finishing eval thread"); } return RNull.instance; @@ -170,51 +195,61 @@ public class FastRContext { * sublist contains the result of the evaluation with name "result". It may also have an * attribute "error" if the evaluation threw an exception, in which case the result will be NA. */ - @RBuiltin(name = ".fastr.context.eval", kind = PRIMITIVE, parameterNames = {"exprs", "pc", "kind"}, behavior = COMPLEX) - public abstract static class Eval extends RBuiltinNode { + @RBuiltin(name = ".fastr.context.eval", kind = PRIMITIVE, parameterNames = {"exprs", "kind"}, behavior = COMPLEX) + public abstract static class Eval extends RBuiltinNode.Arg2 { @Override public Object[] getDefaultParameterValues() { - return new Object[]{RMissing.instance, 1, "SHARE_NOTHING"}; + return new Object[]{RMissing.instance, FastROptions.SharedContexts.getBooleanValue() ? "SHARE_ALL" : "SHARE_NOTHING"}; } static { Casts casts = new Casts(Eval.class); CastsHelper.exprs(casts); - CastsHelper.pc(casts); CastsHelper.kind(casts); } @Specialization @TruffleBoundary - protected Object eval(RAbstractStringVector exprs, int pc, String kind) { + protected Object eval(RAbstractStringVector exprs, String kind) { RContext.ContextKind contextKind = RContext.ContextKind.valueOf(kind); + if (FastROptions.SharedContexts.getBooleanValue() && contextKind != ContextKind.SHARE_ALL) { + throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, "Only shared contexts are allowed"); + } + handleSharedContexts(contextKind); - Object[] results = new Object[pc]; - if (pc == 1) { + int length = exprs.getLength(); + Object[] results = new Object[length]; + if (length == 1) { ContextInfo info = createContextInfo(contextKind); PolyglotEngine vm = info.createVM(); try { - results[0] = RContext.EvalThread.run(vm, info, RSource.fromTextInternal(exprs.getDataAt(0), RSource.Internal.CONTEXT_EVAL)); + results[0] = RContext.EvalThread.run(vm, info, RSource.fromTextInternalInvisible(exprs.getDataAt(0), RSource.Internal.CONTEXT_EVAL)); } finally { vm.dispose(); } } else { // separate threads that run in parallel; invoking thread waits for completion - RContext.EvalThread[] threads = new RContext.EvalThread[pc]; - for (int i = 0; i < pc; i++) { + RContext.EvalThread[] threads = new RContext.EvalThread[length]; + for (int i = 0; i < length; i++) { ContextInfo info = createContextInfo(contextKind); - threads[i] = new RContext.EvalThread(info, RSource.fromTextInternal(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL)); + threads[i] = new RContext.EvalThread(info, RSource.fromTextInternalInvisible(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL)); + } + if (contextKind == ContextKind.SHARE_ALL) { + REnvironment.convertSearchpathToMultiSlot(); } - for (int i = 0; i < pc; i++) { + for (int i = 0; i < length; i++) { threads[i].start(); } + for (int i = 0; i < length; i++) { + threads[i].waitForInit(); + } try { - for (int i = 0; i < pc; i++) { + for (int i = 0; i < length; i++) { threads[i].join(); results[i] = threads[i].getEvalResult(); } } catch (InterruptedException ex) { - throw RError.error(this, RError.Message.GENERIC, "error finishing eval thread"); + throw error(RError.Message.GENERIC, "error finishing eval thread"); } } return RDataFactory.createList(results); @@ -222,7 +257,7 @@ public class FastRContext { } @RBuiltin(name = ".fastr.context.r", kind = PRIMITIVE, visibility = OFF, parameterNames = {"args", "env", "intern"}, behavior = COMPLEX) - public abstract static class R extends RBuiltinNode { + public abstract static class R extends RBuiltinNode.Arg3 { @Override public Object[] getDefaultParameterValues() { return new Object[]{RMissing.instance, RMissing.instance, RRuntime.LOGICAL_FALSE}; @@ -235,6 +270,8 @@ public class FastRContext { casts.arg("intern").asLogicalVector().findFirst().map(toBoolean()); } + public abstract Object execute(VirtualFrame frame, RAbstractStringVector args, RAbstractStringVector env, boolean intern); + @Specialization @TruffleBoundary protected Object r(RAbstractStringVector args, RAbstractStringVector env, boolean intern) { @@ -255,7 +292,7 @@ public class FastRContext { } @RBuiltin(name = ".fastr.context.rscript", kind = PRIMITIVE, visibility = OFF, parameterNames = {"args", "env", "intern"}, behavior = COMPLEX) - public abstract static class Rscript extends RBuiltinNode { + public abstract static class Rscript extends RBuiltinNode.Arg3 { public abstract Object execute(RAbstractStringVector args, RAbstractStringVector env, boolean intern); @@ -274,8 +311,7 @@ public class FastRContext { @Specialization @TruffleBoundary protected Object rscript(RAbstractStringVector args, RAbstractStringVector env, boolean intern) { - Object rc = RContext.getRRuntimeASTAccess().rscriptMain(args.materialize().getDataCopy(), env.materialize().getDataCopy(), intern); - return rc; + return RContext.getRRuntimeASTAccess().rscriptMain(args.materialize().getDataCopy(), env.materialize().getDataCopy(), intern); } @Specialization @@ -283,12 +319,6 @@ public class FastRContext { protected Object rscript(RAbstractStringVector args, @SuppressWarnings("unused") RMissing env, boolean intern) { return rscript(args, RDataFactory.createEmptyStringVector(), intern); } - - @Specialization - @TruffleBoundary - protected Object rscript(@SuppressWarnings("unused") RMissing args, RAbstractStringVector env, boolean intern) { - return rscript(RDataFactory.createEmptyStringVector(), env, intern); - } } private static ContextInfo createContextInfo(RContext.ContextKind contextKind) { @@ -296,7 +326,7 @@ public class FastRContext { } @RBuiltin(name = ".fastr.channel.create", kind = PRIMITIVE, parameterNames = {"key"}, behavior = COMPLEX) - public abstract static class CreateChannel extends RBuiltinNode { + public abstract static class CreateChannel extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(CreateChannel.class); @@ -311,7 +341,7 @@ public class FastRContext { } @RBuiltin(name = ".fastr.channel.get", kind = PRIMITIVE, parameterNames = {"key"}, behavior = COMPLEX) - public abstract static class GetChannel extends RBuiltinNode { + public abstract static class GetChannel extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(GetChannel.class); @@ -326,7 +356,7 @@ public class FastRContext { } @RBuiltin(name = ".fastr.channel.close", visibility = OFF, kind = PRIMITIVE, parameterNames = {"id"}, behavior = COMPLEX) - public abstract static class CloseChannel extends RBuiltinNode { + public abstract static class CloseChannel extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(CloseChannel.class); @@ -342,7 +372,7 @@ public class FastRContext { } @RBuiltin(name = ".fastr.channel.send", visibility = OFF, kind = PRIMITIVE, parameterNames = {"id", "data"}, behavior = COMPLEX) - public abstract static class ChannelSend extends RBuiltinNode { + public abstract static class ChannelSend extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(ChannelSend.class); @@ -358,7 +388,7 @@ public class FastRContext { } @RBuiltin(name = ".fastr.channel.receive", kind = PRIMITIVE, parameterNames = {"id"}, behavior = COMPLEX) - public abstract static class ChannelReceive extends RBuiltinNode { + public abstract static class ChannelReceive extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(ChannelReceive.class); @@ -373,7 +403,7 @@ public class FastRContext { } @RBuiltin(name = ".fastr.channel.poll", kind = PRIMITIVE, parameterNames = {"id"}, behavior = COMPLEX) - public abstract static class ChannelPoll extends RBuiltinNode { + public abstract static class ChannelPoll extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(ChannelPoll.class); @@ -388,7 +418,7 @@ public class FastRContext { } @RBuiltin(name = ".fastr.channel.select", kind = PRIMITIVE, parameterNames = {"ids"}, behavior = COMPLEX) - public abstract static class ChannelSelect extends RBuiltinNode { + public abstract static class ChannelSelect extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(ChannelSelect.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRDebug.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRDebug.java index 6dd3870946dc0b52c010c7690ddbb329cab61706..2ab883be50ae2b95d5a443feca382c2b38d9168f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRDebug.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRDebug.java @@ -31,23 +31,36 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = ".fastr.debug", visibility = OFF, kind = PRIMITIVE, parameterNames = {"values"}, behavior = COMPLEX) -public abstract class FastRDebug extends RBuiltinNode { +public abstract class FastRDebug extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(FastRDebug.class); - casts.arg("values").asStringVector(); + casts.arg("values").allowNullAndMissing().asStringVector(); } @Specialization @TruffleBoundary - protected RNull debug(RAbstractStringVector vec) { - for (int i = 0; i < vec.getLength(); i++) { - FastROptions.debugUpdate(vec.getDataAt(i)); + protected RNull debug(RAbstractStringVector values) { + for (int i = 0; i < values.getLength(); i++) { + FastROptions.debugUpdate(values.getDataAt(i)); } return RNull.instance; } + + @Specialization + @TruffleBoundary + protected RNull debug(@SuppressWarnings("unused") RNull values) { + return RNull.instance; + } + + @Specialization + @TruffleBoundary + protected RNull debug(@SuppressWarnings("unused") RMissing values) { + return RNull.instance; + } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRIdentity.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRIdentity.java index 5b76a6ac968905d6039b7e8c80a0707e08b4a6ca..5f3b6b3a2afc833b6cfbeb9f1086c2cb5865d1c2 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRIdentity.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRIdentity.java @@ -31,7 +31,7 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @RBuiltin(name = ".fastr.identity", kind = PRIMITIVE, parameterNames = {""}, behavior = COMPLEX) -public abstract class FastRIdentity extends RBuiltinNode { +public abstract class FastRIdentity extends RBuiltinNode.Arg1 { static { Casts.noCasts(FastRIdentity.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInspect.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInspect.java index 39cb3d17be08313cfcb2b864857c22afde8472db..5454bf483eb322eb41c4b4949bd4fbe4eba7395f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInspect.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInspect.java @@ -36,7 +36,7 @@ import com.oracle.truffle.r.runtime.data.RNull; * Just a convenient way to inspect values in the Java debugger from the R shell. */ @RBuiltin(name = ".fastr.inspect", visibility = OFF, kind = PRIMITIVE, parameterNames = {"..."}, behavior = COMPLEX) -public abstract class FastRInspect extends RBuiltinNode { +public abstract class FastRInspect extends RBuiltinNode.Arg1 { static { Casts.noCasts(FastRInspect.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java index 16cc34b1b57661dc0db381a6f0d57db48be81cd0..0857f0b53170e67e2b6042ce574718bad030cbff 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java @@ -40,29 +40,60 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.interop.ArityException; 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.interop.java.JavaInterop; import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.Source.Builder; import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.rawValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.typeName; +import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; 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.RSource; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RInteropScalar; +import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropByte; +import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropChar; +import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropFloat; +import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropLong; +import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropShort; +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.RRaw; import com.oracle.truffle.r.runtime.data.RTypedValue; +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.RAbstractLogicalVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import java.lang.reflect.Array; +import java.util.logging.Level; +import java.util.logging.Logger; public class FastRInterop { @RBuiltin(name = ".fastr.interop.eval", visibility = OFF, kind = PRIMITIVE, parameterNames = {"mimeType", "source"}, behavior = COMPLEX) - public abstract static class Eval extends RBuiltinNode { + public abstract static class Eval extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(Eval.class); @@ -77,7 +108,7 @@ public class FastRInterop { try { return RContext.getInstance().getEnv().parse(sourceObject); } catch (Throwable t) { - throw RError.error(this, Message.GENERIC, "Error while parsing: " + t.getMessage()); + throw error(RError.Message.GENERIC, "Error while parsing: " + t.getMessage()); } } @@ -102,7 +133,7 @@ public class FastRInterop { } @RBuiltin(name = ".fastr.interop.evalFile", visibility = OFF, kind = PRIMITIVE, parameterNames = {"path", "mimeType"}, behavior = COMPLEX) - public abstract static class EvalFile extends RBuiltinNode { + public abstract static class EvalFile extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(EvalFile.class); @@ -122,9 +153,9 @@ public class FastRInterop { Source sourceObject = sourceBuilder.build(); return RContext.getInstance().getEnv().parse(sourceObject); } catch (IOException e) { - throw RError.error(this, Message.GENERIC, "Error reading file: " + e.getMessage()); + throw error(RError.Message.GENERIC, "Error reading file: " + e.getMessage()); } catch (Throwable t) { - throw RError.error(this, Message.GENERIC, "Error while parsing: " + t.getMessage()); + throw error(RError.Message.GENERIC, "Error while parsing: " + t.getMessage()); } } @@ -142,7 +173,7 @@ public class FastRInterop { } @RBuiltin(name = ".fastr.interop.export", visibility = OFF, kind = PRIMITIVE, parameterNames = {"name", "value"}, behavior = COMPLEX) - public abstract static class Export extends RBuiltinNode { + public abstract static class Export extends RBuiltinNode.Arg2 { static { Casts casts = new Casts(Export.class); @@ -154,7 +185,7 @@ public class FastRInterop { @TruffleBoundary protected Object exportSymbol(String name, RTypedValue value) { if (name == null) { - throw RError.error(this, RError.Message.INVALID_ARG_TYPE, "name"); + throw error(RError.Message.INVALID_ARGUMENT, "name"); } RContext.getInstance().getExportedSymbols().put(name, value); return RNull.instance; @@ -163,18 +194,18 @@ public class FastRInterop { @Specialization @TruffleBoundary protected Object exportSymbol(@SuppressWarnings("unused") String name, @SuppressWarnings("unused") RMissing value) { - throw RError.error(this, Message.ARGUMENT_MISSING, "value"); + throw error(RError.Message.ARGUMENT_MISSING, "value"); } @Fallback @TruffleBoundary protected Object exportSymbol(@SuppressWarnings("unused") Object name, @SuppressWarnings("unused") Object value) { - throw RError.error(this, Message.GENERIC, "only R language objects can be exported"); + throw error(RError.Message.GENERIC, "only R language objects can be exported"); } } @RBuiltin(name = ".fastr.interop.import", visibility = OFF, kind = PRIMITIVE, parameterNames = {"name"}, behavior = COMPLEX) - public abstract static class Import extends RBuiltinNode { + public abstract static class Import extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(Import.class); @@ -186,16 +217,16 @@ public class FastRInterop { protected Object importSymbol(String name) { Object object = RContext.getInstance().getEnv().importSymbol(name); if (object == null) { - throw RError.error(this, RError.Message.NO_IMPORT_OBJECT, name); + throw error(RError.Message.NO_IMPORT_OBJECT, name); } return object; } } @RBuiltin(name = ".fastr.interop.hasSize", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX) - public abstract static class HasSize extends RBuiltinNode { + public abstract static class HasSize extends RBuiltinNode.Arg1 { - @Child private Node node = com.oracle.truffle.api.interop.Message.HAS_SIZE.createNode(); + @Child private Node node = Message.HAS_SIZE.createNode(); static { Casts.noCasts(HasSize.class); @@ -208,37 +239,175 @@ public class FastRInterop { } @RBuiltin(name = ".fastr.interop.isNull", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX) - public abstract static class IsNull extends RBuiltinNode { + public abstract static class IsNull extends RBuiltinNode.Arg1 { - @Child private Node node = com.oracle.truffle.api.interop.Message.IS_NULL.createNode(); + @Child private Node node = Message.IS_NULL.createNode(); static { Casts.noCasts(IsNull.class); } @Specialization - public byte hasSize(TruffleObject obj) { + public byte isNull(TruffleObject obj) { return RRuntime.asLogical(ForeignAccess.sendIsNull(node, obj)); } } @RBuiltin(name = ".fastr.interop.isExecutable", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX) - public abstract static class IsExecutable extends RBuiltinNode { + public abstract static class IsExecutable extends RBuiltinNode.Arg1 { - @Child private Node node = com.oracle.truffle.api.interop.Message.IS_EXECUTABLE.createNode(); + @Child private Node node = Message.IS_EXECUTABLE.createNode(); static { Casts.noCasts(IsExecutable.class); } @Specialization - public byte hasSize(TruffleObject obj) { + public byte isExecutable(TruffleObject obj) { return RRuntime.asLogical(ForeignAccess.sendIsExecutable(node, obj)); } } + @RBuiltin(name = ".fastr.interop.toByte", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX) + public abstract static class ToByte extends RBuiltinNode.Arg1 { + + static { + castToJavaNumberType(new Casts(ToByte.class)); + } + + @Specialization + public RInteropByte toByte(int value) { + return RInteropByte.valueOf((byte) value); + } + + @Specialization + public RInteropByte toByte(double value) { + return RInteropByte.valueOf((byte) value); + } + + @Specialization + public RInteropByte toByte(RRaw value) { + return RInteropByte.valueOf(value.getValue()); + } + } + + @RBuiltin(name = ".fastr.interop.toChar", visibility = ON, kind = PRIMITIVE, parameterNames = {"value", "pos"}, behavior = COMPLEX) + public abstract static class ToChar extends RBuiltinNode.Arg2 { + + static { + Casts casts = new Casts(ToChar.class); + casts.arg("value").mustBe(integerValue().or(doubleValue().or(stringValue())), RError.Message.INVALID_ARGUMENT_OF_TYPE, "value", Predef.typeName()).asVector().mustBe( + singleElement()).findFirst(); + casts.arg("pos").allowMissing().mustBe(numericValue(), RError.Message.INVALID_ARGUMENT_OF_TYPE, "pos", Predef.typeName()).asIntegerVector().mustBe(singleElement()).findFirst(); + } + + @Specialization + public RInteropChar toChar(int value, @SuppressWarnings("unused") RMissing unused) { + return RInteropChar.valueOf((char) value); + } + + @Specialization + public RInteropChar toChar(double value, @SuppressWarnings("unused") RMissing unused) { + return RInteropChar.valueOf((char) value); + } + + @Specialization + public RInteropChar toChar(String value, @SuppressWarnings("unused") RMissing unused) { + return toChar(value, 0); + } + + @Specialization + public RInteropChar toChar(int value, int pos) { + throw RError.error(this, RError.Message.POS_NOT_ALLOWED_WITH_NUMERIC); + } + + @Specialization + public RInteropChar toChar(double value, int pos) { + throw RError.error(this, RError.Message.POS_NOT_ALLOWED_WITH_NUMERIC); + } + + @Specialization + public RInteropChar toChar(String value, int pos) { + return RInteropChar.valueOf(value.charAt(pos)); + } + } + + @RBuiltin(name = ".fastr.interop.toFloat", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX) + public abstract static class ToFloat extends RBuiltinNode.Arg1 { + + static { + castToJavaNumberType(new Casts(ToFloat.class)); + } + + @Specialization + public RInteropFloat toFloat(int value) { + return RInteropFloat.valueOf((float) value); + } + + @Specialization + public RInteropFloat toFloat(double value) { + return RInteropFloat.valueOf((float) value); + } + + @Specialization + public RInteropFloat toFloat(RRaw value) { + return RInteropFloat.valueOf(value.getValue()); + } + } + + @RBuiltin(name = ".fastr.interop.toLong", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX) + public abstract static class ToLong extends RBuiltinNode.Arg1 { + + static { + castToJavaNumberType(new Casts(ToLong.class)); + } + + @Specialization + public RInteropLong toLong(int value) { + return RInteropLong.valueOf((long) value); + } + + @Specialization + public RInteropLong toLong(double value) { + return RInteropLong.valueOf((long) value); + } + + @Specialization + public RInteropLong toLong(RRaw value) { + return RInteropLong.valueOf(value.getValue()); + } + } + + @RBuiltin(name = ".fastr.interop.toShort", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX) + public abstract static class ToShort extends RBuiltinNode.Arg1 { + + static { + castToJavaNumberType(new Casts(ToShort.class)); + } + + @Specialization + public RInteropShort toShort(double value) { + return RInteropShort.valueOf((short) value); + } + + @Specialization + public RInteropShort toShort(int value) { + return RInteropShort.valueOf((short) value); + } + + @Specialization + public RInteropShort toShort(RRaw value) { + return RInteropShort.valueOf(value.getValue()); + } + + } + + private static void castToJavaNumberType(Casts casts) { + casts.arg("value").mustBe(integerValue().or(doubleValue().or(rawValue())), RError.Message.INVALID_ARGUMENT_OF_TYPE, "value", Predef.typeName()).asVector().mustBe(singleElement()).findFirst(); + } + @RBuiltin(name = ".fastr.interop.toBoolean", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX) - public abstract static class ToBoolean extends RBuiltinNode { + public abstract static class ToBoolean extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(ToBoolean.class); @@ -250,4 +419,391 @@ public class FastRInterop { return value; } } + + @RBuiltin(name = ".fastr.java.class", visibility = ON, kind = PRIMITIVE, parameterNames = {"class"}, behavior = COMPLEX) + public abstract static class JavaClass extends RBuiltinNode.Arg1 { + + static { + Casts casts = new Casts(JavaClass.class); + casts.arg("class").mustBe(stringValue()).asStringVector().mustBe(Predef.singleElement()).findFirst(); + } + + @Specialization + @TruffleBoundary + public TruffleObject javaClass(String clazz) { + try { + return JavaInterop.asTruffleObject(Class.forName(clazz)); + } catch (ClassNotFoundException | SecurityException | IllegalArgumentException e) { + throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage()); + } + } + } + + @ImportStatic({Message.class, RRuntime.class}) + @RBuiltin(name = ".fastr.java.isArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"obj"}, behavior = COMPLEX) + public abstract static class IsJavaArray extends RBuiltinNode.Arg1 { + + static { + Casts.noCasts(IsJavaArray.class); + } + + private final ConditionProfile isJavaProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile isArrayProfile = ConditionProfile.createBinaryProfile(); + + @Specialization(guards = {"isForeignObject(obj)"}) + @TruffleBoundary + public Object isArray(TruffleObject obj) { + // TODO does this return true only for java arrays, or also + // js arrays? + boolean result = isJavaProfile.profile(JavaInterop.isJavaObject(Object.class, obj)) && isArrayProfile.profile(JavaInterop.isArray(obj)); + return RRuntime.java2R(result); + } + + @Fallback + public Object isArray(Object obj) { + return RRuntime.java2R(false); + } + } + + @RBuiltin(name = ".fastr.java.newArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"class", "dim"}, behavior = COMPLEX) + public abstract static class NewJavaArray extends RBuiltinNode.Arg2 { + + static { + Casts casts = new Casts(NewJavaArray.class); + casts.arg("class").mustBe(stringValue()).asStringVector().mustBe(Predef.singleElement()).findFirst(); + casts.arg("dim").mustBe(integerValue(), RError.Message.INVALID_ARGUMENT_OF_TYPE, "dim", typeName()).asIntegerVector(); + } + + @Specialization + @TruffleBoundary + public Object newArray(String clazz, int length) { + try { + // TODO new via ForeignAccess + return JavaInterop.asTruffleObject(Array.newInstance(Class.forName(clazz), length)); + } catch (ClassNotFoundException e) { + throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage()); + } + } + + @Specialization + @TruffleBoundary + public Object newArray(String clazz, RAbstractIntVector dim) { + try { + int[] dima = new int[dim.getLength()]; + // TODO new via ForeignAccess + return JavaInterop.asTruffleObject(Array.newInstance(Class.forName(clazz), dima)); + } catch (ClassNotFoundException e) { + throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage()); + } + } + } + + @ImportStatic({Message.class, RRuntime.class}) + @RBuiltin(name = ".fastr.java.toArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"x", "className", "flat"}, behavior = COMPLEX) + public abstract static class ToJavaArray extends RBuiltinNode.Arg3 { + + static { + Casts casts = new Casts(ToJavaArray.class); + casts.arg("x").mustNotBeMissing(); + casts.arg("className").allowMissing().mustBe(stringValue()).asStringVector().mustBe(Predef.singleElement()).findFirst(); + casts.arg("flat").mapMissing(Predef.constant(RRuntime.asLogical(true))).mustBe(logicalValue().or(Predef.nullValue())).asLogicalVector().mustBe(singleElement()).findFirst().mustBe( + notLogicalNA()).map(Predef.toBoolean()); + } + + @Specialization + @TruffleBoundary + public Object toArray(RAbstractLogicalVector vec, @SuppressWarnings("unused") RMissing className, boolean flat) { + return toArray(vec, flat, boolean.class, (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAt(i)))); + } + + @Specialization + @TruffleBoundary + public Object toArray(RAbstractLogicalVector vec, String className, boolean flat) { + return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAt(i)))); + } + + @Specialization + @TruffleBoundary + public Object toArray(RAbstractIntVector vec, @SuppressWarnings("unused") RMissing className, boolean flat) { + return toArray(vec, flat, int.class, (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAt(i)))); + } + + @Specialization + @TruffleBoundary + public Object toArray(RAbstractIntVector vec, String className, boolean flat) { + return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, vec.getDataAt(i))); + } + + @Specialization + @TruffleBoundary + public Object toArray(RAbstractDoubleVector vec, @SuppressWarnings("unused") RMissing className, boolean flat) { + return toArray(vec, flat, double.class, (array, i) -> Array.set(array, i, vec.getDataAt(i))); + } + + @Specialization + @TruffleBoundary + public Object toArray(RAbstractDoubleVector vec, String className, boolean flat) { + return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, vec.getDataAt(i))); + } + + @Specialization + @TruffleBoundary + public Object toArray(RAbstractStringVector vec, @SuppressWarnings("unused") RMissing className, boolean flat) { + return toArray(vec, flat, String.class, (array, i) -> Array.set(array, i, vec.getDataAt(i))); + } + + @Specialization + @TruffleBoundary + public Object toArray(RAbstractStringVector vec, String className, boolean flat) { + return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, vec.getDataAt(i))); + } + + @Specialization + @TruffleBoundary + public Object toArray(RAbstractVector vec, @SuppressWarnings("unused") RMissing className, boolean flat) { + return toArray(vec, flat, Object.class, (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAtAsObject(i)))); + } + + @Specialization + @TruffleBoundary + public Object toArray(RAbstractVector vec, String className, boolean flat) { + return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAtAsObject(i)))); + } + + @Specialization + @TruffleBoundary + public Object toArray(RInteropScalar ri, String className, boolean flat) { + RList list = RDataFactory.createList(new Object[]{ri}); + return toArray(list, flat, getClazz(className), (array, i) -> Array.set(array, i, RRuntime.r2Java(list.getDataAt(i)))); + } + + @Specialization + @TruffleBoundary + public Object toArray(RInteropScalar ri, RMissing className, boolean flat) { + RList list = RDataFactory.createList(new Object[]{ri}); + return toArray(list, flat, ri.getJavaType(), (array, i) -> Array.set(array, i, RRuntime.r2Java(list.getDataAt(i)))); + } + + private Class<?> getClazz(String className) throws RError { + if (className.equals(Byte.TYPE.getName())) { + return Byte.TYPE; + } + if (className.equals(Boolean.TYPE.getName())) { + return Boolean.TYPE; + } + if (className.equals(Character.TYPE.getName())) { + return Character.TYPE; + } + if (className.equals(Double.TYPE.getName())) { + return Double.TYPE; + } + if (className.equals(Float.TYPE.getName())) { + return Float.TYPE; + } + if (className.equals(Integer.TYPE.getName())) { + return Integer.TYPE; + } + if (className.equals(Long.TYPE.getName())) { + return Long.TYPE; + } + if (className.equals(Short.TYPE.getName())) { + return Short.TYPE; + } + try { + return Class.forName(className); + } catch (ClassNotFoundException e) { + throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage()); + } + } + + private int[] getDim(boolean flat, RAbstractVector vec) { + int[] dims; + if (flat) { + dims = new int[]{vec.getLength()}; + } else { + dims = vec.getDimensions(); + if (dims == null) { + dims = new int[]{vec.getLength()}; + } + } + return dims; + } + + private Object toArray(RAbstractVector vec, boolean flat, Class<?> clazz, VecElementToArray vecToArray) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { + int[] dims = getDim(flat, vec); + final Object array = Array.newInstance(clazz, dims); + for (int d = 0; d < dims.length; d++) { + int dim = dims[d]; + // TODO works only for flat + for (int i = 0; i < dim; i++) { + vecToArray.toArray(array, i); + } + } + return JavaInterop.asTruffleObject(array); + } + + private interface VecElementToArray { + void toArray(Object array, Integer i); + } + + @Specialization + @TruffleBoundary + public Object toArray(TruffleObject obj, @SuppressWarnings("unused") RMissing missing, @SuppressWarnings("unused") boolean flat, + @Cached("WRITE.createNode()") Node write) { + if (JavaInterop.isJavaObject(Object.class, obj)) { + if (JavaInterop.isArray(obj)) { + // TODO should return copy? + return obj; + } + try { + // TODO should create array with the same component type as the JavaObject + TruffleObject array = JavaInterop.asTruffleObject(Array.newInstance(Object.class, 1)); + ForeignAccess.sendWrite(write, array, 0, obj); + return array; + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw error(RError.Message.GENERIC, "error while creating array: " + e.getMessage()); + } catch (UnsupportedTypeException ex) { + Logger.getLogger(FastRInterop.class.getName()).log(Level.SEVERE, null, ex); + } + } + throw error(RError.Message.GENERIC, "can't create array from " + obj); + } + + @Fallback + public Object toArray(Object o, @SuppressWarnings("unused") Object className, @SuppressWarnings("unused") Object flat) { + throw error(RError.Message.GENERIC, "unsupported type"); + } + + } + + @RBuiltin(name = ".fastr.java.fromArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"array"}, behavior = COMPLEX) + public abstract static class FromJavaArray extends RBuiltinNode.Arg1 { + @Child Node getSize = Message.GET_SIZE.createNode(); + @Child Node read; + @Child Node isNull; + @Child Node isBoxed; + @Child Node unbox; + static { + Casts casts = new Casts(FromJavaArray.class); + casts.arg("array").mustNotBeMissing(); + } + + protected boolean isJavaArray(TruffleObject obj) { + return JavaInterop.isJavaObject(Object.class, obj) && JavaInterop.isArray(obj); + } + + @Specialization(guards = {"isJavaArray(obj)"}) + @TruffleBoundary + public Object fromArray(TruffleObject obj) { + int size; + try { + size = (int) ForeignAccess.sendGetSize(getSize, obj); + if (size == 0) { + return RDataFactory.createList(); + } + Object[] elements = new Object[size]; + boolean allBoolean = true; + boolean allInteger = true; + boolean allDouble = true; + boolean allString = true; + for (int i = 0; i < size; i++) { + if (read == null) { + read = insert(Message.READ.createNode()); + } + Object element = ForeignAccess.sendRead(read, obj, i); + if (element instanceof TruffleObject) { + if (isNull == null) { + isNull = insert(Message.IS_NULL.createNode()); + } + if (ForeignAccess.sendIsNull(isNull, (TruffleObject) element)) { + element = null; + } else { + if (isBoxed == null) { + isBoxed = insert(Message.IS_BOXED.createNode()); + } + if (ForeignAccess.sendIsBoxed(isBoxed, (TruffleObject) element)) { + if (unbox == null) { + unbox = insert(Message.UNBOX.createNode()); + } + element = ForeignAccess.sendIsBoxed(unbox, (TruffleObject) element); + } + } + } + allBoolean &= element instanceof Boolean; + allInteger &= element instanceof Byte || element instanceof Integer || element instanceof Short; + allDouble &= element instanceof Double || element instanceof Float || element instanceof Long; + allString &= element instanceof Character || element instanceof String; + + elements[i] = RRuntime.java2R(element); + } + if (allBoolean) { + byte[] ret = new byte[size]; + for (int i = 0; i < size; i++) { + ret[i] = ((Number) elements[i]).byteValue(); + } + return RDataFactory.createLogicalVector(ret, true); + } + if (allInteger) { + int[] ret = new int[size]; + for (int i = 0; i < size; i++) { + ret[i] = ((Number) elements[i]).intValue(); + } + return RDataFactory.createIntVector(ret, true); + } + if (allDouble) { + double[] ret = new double[size]; + for (int i = 0; i < size; i++) { + ret[i] = ((Number) elements[i]).doubleValue(); + } + return RDataFactory.createDoubleVector(ret, true); + } + if (allString) { + String[] ret = new String[size]; + for (int i = 0; i < size; i++) { + ret[i] = String.valueOf(elements[i]); + } + return RDataFactory.createStringVector(ret, true); + } + return RDataFactory.createList(elements); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw error(RError.Message.GENERIC, "error while converting array: " + e.getMessage()); + } + } + + @Fallback + public Object fromArray(@SuppressWarnings("unused") Object obj) { + throw error(RError.Message.GENERIC, "not a java array"); + } + } + + @ImportStatic({Message.class, RRuntime.class}) + @RBuiltin(name = ".fastr.interop.new", visibility = ON, kind = PRIMITIVE, parameterNames = {"class", "..."}, behavior = COMPLEX) + public abstract static class InteropNew extends RBuiltinNode.Arg2 { + + static { + Casts.noCasts(InteropNew.class); + } + + @Specialization(limit = "99", guards = {"isForeignObject(clazz)", "length == args.getLength()"}) + @TruffleBoundary + public Object interopNew(TruffleObject clazz, RArgsValuesAndNames args, + @SuppressWarnings("unused") @Cached("args.getLength()") int length, + @Cached("createNew(length).createNode()") Node sendNew) { + try { + Object[] argValues = new Object[args.getLength()]; + for (int i = 0; i < argValues.length; i++) { + argValues[i] = RRuntime.r2Java(args.getArgument(i)); + } + Object result = ForeignAccess.sendNew(sendNew, clazz, argValues); + return RRuntime.java2R(result); + } catch (SecurityException | IllegalArgumentException | UnsupportedTypeException | ArityException | UnsupportedMessageException e) { + throw error(RError.Message.GENERIC, "error during Java object instantiation: " + e.getMessage()); + } + } + + @Fallback + public Object interopNew(@SuppressWarnings("unused") Object clazz, @SuppressWarnings("unused") Object args) { + throw error(RError.Message.GENERIC, "interop object needed as receiver of NEW message"); + } + } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java index 0306c6dc7a9167fbf5df2da024ede7f38acbe35f..ebb579bb12c6d3be3d656752dd70eb0af23610c3 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java @@ -34,6 +34,7 @@ import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; @@ -60,7 +61,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment; * {@code Rpkgsource} directory., for use by e.g., a source-level debugger. */ @RBuiltin(name = ".fastr.pkgsource", kind = PRIMITIVE, visibility = OFF, parameterNames = {"pkgs", "verbose"}, behavior = COMPLEX) -public abstract class FastRPkgSource extends RBuiltinNode { +public abstract class FastRPkgSource extends RBuiltinNode.Arg2 { public static final String PKGSOURCE_PROJECT = "Rpkgsource"; private static final String SLASH_SWAP = "_slash_"; @@ -71,12 +72,13 @@ public abstract class FastRPkgSource extends RBuiltinNode { static { Casts casts = new Casts(FastRPkgSource.class); - casts.arg("pkgs").mustBe(stringValue()); - casts.arg("verbose").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("pkgs").allowNull().mustBe(stringValue()); + casts.arg("verbose").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } @Specialization public RNull pkgSource(VirtualFrame frame, @SuppressWarnings("unused") RNull pkgs, boolean verbose) { + CompilerDirectives.transferToInterpreter(); String[] searchPath = REnvironment.searchPath(); for (String s : searchPath) { REnvironment env = REnvironment.lookupOnSearchPath(s); @@ -90,6 +92,7 @@ public abstract class FastRPkgSource extends RBuiltinNode { @Specialization public RNull pkgSource(VirtualFrame frame, RAbstractStringVector pkgs, boolean verbose) { + CompilerDirectives.transferToInterpreter(); for (int i = 0; i < pkgs.getLength(); i++) { String pkg = pkgs.getDataAt(i); REnvironment env = REnvironment.getRegisteredNamespace(pkg); @@ -133,22 +136,22 @@ public abstract class FastRPkgSource extends RBuiltinNode { try { StdConnections.getStdout().writeString(msg, nl); } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, ex.getMessage()); + throw error(RError.Message.GENERIC, ex.getMessage()); } } @TruffleBoundary private void notFound(String pkg) { - RError.warning(this, RError.Message.GENERIC, String.format("namespace '%s' not found - ignoring", pkg)); + warning(RError.Message.GENERIC, String.format("namespace '%s' not found - ignoring", pkg)); } @TruffleBoundary private void noDeparse(String pkg, String fname) { - RError.warning(this, RError.Message.GENERIC, String.format("function '%s::%s' failed to deparse - ignoring", pkg, fname)); + warning(RError.Message.GENERIC, String.format("function '%s::%s' failed to deparse - ignoring", pkg, fname)); } @TruffleBoundary - private static void saveSource(String pkg, String fname, String deparseResult) { + private void saveSource(String pkg, String fname, String deparseResult) { RSerialize.setSaveDeparse(false); try { Path target = targetPath(pkg, fname); @@ -156,7 +159,7 @@ public abstract class FastRPkgSource extends RBuiltinNode { wr.write(deparseResult); } } catch (IOException ex) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, ex.getMessage()); + throw error(RError.Message.GENERIC, ex.getMessage()); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRRefCountInfo.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRRefCountInfo.java index a9e8cee05edafc523f5399c3ee63f76324ee33d0..b6634b88c34d0aff430a638615bfd39806ce32c3 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRRefCountInfo.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRRefCountInfo.java @@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.data.RShareable; * for permanent shared */ @RBuiltin(name = ".fastr.refcountinfo", kind = PRIMITIVE, parameterNames = {""}, behavior = COMPLEX) -public abstract class FastRRefCountInfo extends RBuiltinNode { +public abstract class FastRRefCountInfo extends RBuiltinNode.Arg1 { static { Casts.noCasts(FastRRefCountInfo.class); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSlotAssign.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSlotAssign.java new file mode 100644 index 0000000000000000000000000000000000000000..a4bdf0126efc6f58423c856f6af5bdcc6e0c83e1 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSlotAssign.java @@ -0,0 +1,78 @@ +/* + * 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.nodes.builtin.CastBuilder.Predef.singleElement; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; +import static com.oracle.truffle.r.runtime.RVisibility.ON; +import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; +import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; + +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.r.nodes.access.UpdateSlotNode; +import com.oracle.truffle.r.nodes.access.UpdateSlotNodeGen; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.base.UpdateAttr.InternStringNode; +import com.oracle.truffle.r.nodes.builtin.base.UpdateAttrNodeGen.InternStringNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.UpdateSlot.CheckSlotAssignNode; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RMissing; + +@RBuiltin(name = ".fastr.methods.slotassign", visibility = ON, kind = PRIMITIVE, parameterNames = {"object", "name", "check", "value"}, behavior = COMPLEX) +public abstract class FastRSlotAssign extends RBuiltinNode.Arg4 { + + static { + Casts casts = new Casts(FastRSlotAssign.class); + casts.arg("object").mustNotBeNull(); + casts.arg("name").defaultError(Message.SLOT_INVALID_TYPE_OR_LEN).mustNotBeMissing().mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst(); + casts.arg("check").mustNotBeMissing().asLogicalVector().findFirst().mustNotBeNA(Message.NA_UNEXP).map(toBoolean()); + casts.arg("value").mustNotBeMissing(); + } + + @Child private InternStringNode intern = InternStringNodeGen.create(); + @Child private UpdateSlotNode updateSlotNode = UpdateSlotNodeGen.create(); + + @Override + public Object[] getDefaultParameterValues() { + return new Object[]{RMissing.instance, RMissing.instance, RRuntime.LOGICAL_TRUE, RMissing.instance}; + } + + @Specialization(guards = "check") + public Object assign(VirtualFrame frame, Object object, String name, @SuppressWarnings("unused") boolean check, Object value, + @Cached("new()") CheckSlotAssignNode checkNode) { + String interned = intern.execute(name); + checkNode.execute(frame, object, interned, value); + return updateSlotNode.executeUpdate(object, interned, value); + } + + @Specialization(guards = "!check") + public Object assign(Object object, String name, @SuppressWarnings("unused") boolean check, Object value) { + String interned = intern.execute(name); + return updateSlotNode.executeUpdate(object, interned, value); + } +} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java index f2b4d2b4d54af8bc4024cea49df6cf1b5b5b8679..b7179ade00d55bd5bad8fd8e03c96728bb9837a9 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java @@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RNull; @RBuiltin(name = ".fastr.stacktrace", visibility = OFF, kind = PRIMITIVE, parameterNames = {"print.frame.contents"}, behavior = COMPLEX) -public abstract class FastRStackTrace extends RBuiltinNode { +public abstract class FastRStackTrace extends RBuiltinNode.Arg1 { @Override public Object[] getDefaultParameterValues() { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java index 16abbd8f1637e254b177583593c0f21dabdc7cb0..458fa6ebeff90250e215b59b64ec750d1755edde 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java @@ -68,12 +68,12 @@ public class FastRStats { } private static void append(Casts casts) { - casts.arg("append").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).notNA().map(toBoolean()); + casts.arg("append").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).mustNotBeNA().map(toBoolean()); } } @RBuiltin(name = ".fastr.prof.attr", visibility = OFF, kind = PRIMITIVE, parameterNames = {"filename", "append"}, behavior = COMPLEX) - public abstract static class FastRProfAttr extends RBuiltinNode implements AttributeTracer.Listener { + public abstract static class FastRProfAttr extends RBuiltinNode.Arg2 implements AttributeTracer.Listener { @Override public Object[] getDefaultParameterValues() { return new Object[]{"Rprofattr.out", RRuntime.LOGICAL_FALSE}; @@ -108,7 +108,7 @@ public class FastRStats { AttributeTracer.addListener(this); AttributeTracer.setTracingState(true); } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filenameVec.getDataAt(0))); + throw error(RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filenameVec.getDataAt(0))); } } return RNull.instance; @@ -158,7 +158,7 @@ public class FastRStats { } @RBuiltin(name = ".fastr.stats.typecounts", visibility = OFF, kind = PRIMITIVE, parameterNames = {"filename", "append"}, behavior = COMPLEX) - public abstract static class FastRProfTypecounts extends RBuiltinNode implements RDataFactory.Listener { + public abstract static class FastRProfTypecounts extends RBuiltinNode.Arg2 implements RDataFactory.Listener { @Override public Object[] getDefaultParameterValues() { return new Object[]{"Rproftypecounts.out", RRuntime.LOGICAL_FALSE}; @@ -193,7 +193,7 @@ public class FastRStats { RDataFactory.addListener(this); RDataFactory.setTracingState(true); } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filenameVec.getDataAt(0))); + throw error(RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filenameVec.getDataAt(0))); } } return RNull.instance; @@ -289,7 +289,7 @@ public class FastRStats { } @RBuiltin(name = ".fastr.stats.funcounts", visibility = OFF, kind = PRIMITIVE, parameterNames = {"filename", "append", "timing", "threshold", "histograms"}, behavior = COMPLEX) - public abstract static class FastRProfFuncounts extends RBuiltinNode { + public abstract static class FastRProfFuncounts extends RBuiltinNode.Arg5 { @Override public Object[] getDefaultParameterValues() { return new Object[]{"Rproffuncounts.out", RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, 0, RRuntime.LOGICAL_FALSE}; @@ -299,9 +299,9 @@ public class FastRStats { Casts casts = new Casts(FastRProfFuncounts.class); CastsHelper.filename(casts); CastsHelper.append(casts); - casts.arg("timing").asLogicalVector().findFirst().notNA().map(toBoolean()); - casts.arg("threshold").asIntegerVector().findFirst().notNA(); - casts.arg("histograms").asLogicalVector().findFirst().notNA().map(toBoolean()); + casts.arg("timing").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); + casts.arg("threshold").asIntegerVector().findFirst().mustNotBeNA(); + casts.arg("histograms").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean()); } @SuppressWarnings("unused") @@ -328,7 +328,7 @@ public class FastRStats { profiler.setCollecting(true); profiler.setTiming(timing); } catch (IOException ex) { - throw RError.error(this, RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filenameVec.getDataAt(0))); + throw error(RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filenameVec.getDataAt(0))); } } return RNull.instance; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java index 8817ee3bcf7189734a8924abbc357265c6df5791..41e42f0a135329bf7ec09355c304c36d8f4b5aa1 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java @@ -66,7 +66,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor; * */ @RBuiltin(name = ".fastr.syntaxtree", visibility = OFF, kind = PRIMITIVE, parameterNames = {"func", "visitMode", "printSource", "printTags"}, behavior = IO) -public abstract class FastRSyntaxTree extends RBuiltinNode { +public abstract class FastRSyntaxTree extends RBuiltinNode.Arg4 { @Override public Object[] getDefaultParameterValues() { @@ -161,7 +161,7 @@ public abstract class FastRSyntaxTree extends RBuiltinNode { break; default: - throw RError.error(this, RError.Message.INVALID_ARGUMENT, "visitMode"); + throw error(RError.Message.INVALID_ARGUMENT, "visitMode"); } return RNull.instance; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRThrowIt.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRThrowIt.java index aa63c269457a97afd0f10107682f85fc22e5b6d5..648bb944fc34d0a3d91b009ddd55c0665ad92d95 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRThrowIt.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRThrowIt.java @@ -36,7 +36,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RNull; @RBuiltin(name = ".fastr.throw", kind = PRIMITIVE, parameterNames = {"name"}, behavior = COMPLEX) -public abstract class FastRThrowIt extends RBuiltinNode { +public abstract class FastRThrowIt extends RBuiltinNode.Arg1 { static { Casts casts = new Casts(FastRThrowIt.class); @@ -63,7 +63,7 @@ public abstract class FastRThrowIt extends RBuiltinNode { case "BRQ": throw new JumpToTopLevelException(); default: - throw RError.error(this, RError.Message.GENERIC, "unknown case: " + name); + throw error(RError.Message.GENERIC, "unknown case: " + name); } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java index 96eec41e231eac409ac72b9ed067e3c04168ada0..5fe5c8bdbaa9247e8fa149c699164c07e9334188 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java @@ -56,6 +56,7 @@ import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; /** * This a FastR-specific version of the standard {@code trace} function which uses the @@ -66,7 +67,7 @@ import com.oracle.truffle.r.runtime.data.RNull; */ public class FastRTrace { - protected abstract static class Helper extends RBuiltinNode { + static final class Helper extends RBaseNode { @Child private GetFunctions.Get getNode; @Child private EnvFunctions.TopEnv topEnv; @Child private FrameFunctions.ParentFrame parentFrame; @@ -75,9 +76,12 @@ public class FastRTrace { if (topEnv == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); topEnv = insert(TopEnvNodeGen.create()); + } + if (parentFrame == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); parentFrame = insert(ParentFrameNodeGen.create()); } - return topEnv.executeBuiltin(frame, parentFrame.execute(frame, 1), RNull.instance); + return topEnv.execute(frame, parentFrame.execute(frame, 1), RNull.instance); } protected Object getFunction(VirtualFrame frame, Object what, Object where) { @@ -85,12 +89,12 @@ public class FastRTrace { CompilerDirectives.transferToInterpreterAndInvalidate(); getNode = insert(GetNodeGen.create()); } - return getNode.executeBuiltin(frame, what, where, RType.Function.getName(), true); + return getNode.execute(frame, what, where, RType.Function.getName(), true); } protected void checkWhat(Object what) { if (what == RMissing.instance) { - throw RError.error(this, RError.Message.ARGUMENT_MISSING, "what"); + throw error(RError.Message.ARGUMENT_MISSING, "what"); } } @@ -98,22 +102,23 @@ public class FastRTrace { if (what instanceof RFunction) { RFunction func = (RFunction) what; if (func.isBuiltin()) { - throw RError.error(this, RError.Message.GENERIC, "builtin functions cannot be traced"); + throw error(RError.Message.GENERIC, "builtin functions cannot be traced"); } else { return func; } } else { - throw RError.error(this, RError.Message.ARG_MUST_BE_CLOSURE); + throw error(RError.Message.ARG_MUST_BE_CLOSURE); } } } @RBuiltin(name = ".fastr.trace", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"what", "tracer", "exit", "at", "print", "signature", "where"}, behavior = COMPLEX) - public abstract static class Trace extends Helper { + public abstract static class Trace extends RBuiltinNode.Arg7 { @Child private TraceFunctions.PrimTrace primTrace; @Child private CastLogicalNode castLogical; @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); + @Child private Helper helper = new Helper(); static { Casts.noCasts(Trace.class); @@ -122,16 +127,16 @@ public class FastRTrace { @Specialization protected Object trace(VirtualFrame frame, Object whatObj, Object tracer, Object exit, Object at, Object printObj, Object signature, Object whereObj) { Object what = whatObj; - checkWhat(what); + helper.checkWhat(what); Object where = whereObj; if (where == RMissing.instance) { - where = getWhere(frame); + where = helper.getWhere(frame); } String funcName = RRuntime.asString(what); if (funcName != null) { - what = getFunction(frame, what, where); + what = helper.getFunction(frame, what, where); } - RFunction func = checkFunction(what); + RFunction func = helper.checkFunction(what); if (tracer == RMissing.instance && exit == RMissing.instance && at == RMissing.instance && printObj == RMissing.instance && signature == RMissing.instance) { // simple case, nargs() == 1, corresponds to .primTrace that has invisible output @@ -140,7 +145,7 @@ public class FastRTrace { primTrace = insert(PrimTraceNodeGen.create()); } - Object result = primTrace.executeBuiltin(frame, func); + Object result = primTrace.execute(frame, func); visibility.execute(frame, false); return result; } @@ -154,7 +159,7 @@ public class FastRTrace { CompilerDirectives.transferToInterpreterAndInvalidate(); castLogical = insert(CastLogicalNodeGen.create(false, false, false)); } - print = RRuntime.fromLogical((byte) castLogical.execute(printObj)); + print = RRuntime.fromLogical((byte) castLogical.doCast(printObj)); } complexCase(func, tracer, exit, at, print, signature); visibility.execute(frame, true); @@ -171,36 +176,41 @@ public class FastRTrace { } else if (tracerObj instanceof RLanguage) { tracer = (RLanguage) tracerObj; } else { - throw RError.error(this, RError.Message.GENERIC, "tracer is unexpected type"); + throw error(RError.Message.GENERIC, "tracer is unexpected type"); } TraceHandling.enableStatementTrace(func, tracer, exit, at, print); } } @RBuiltin(name = ".fastr.untrace", visibility = OFF, kind = PRIMITIVE, parameterNames = {"what", "signature", "where"}, behavior = COMPLEX) - public abstract static class Untrace extends Helper { + public abstract static class Untrace extends RBuiltinNode.Arg3 { @Child private TraceFunctions.PrimUnTrace primUnTrace; + @Child private Helper helper = new Helper(); + + static { + Casts.noCasts(Untrace.class); + } @Specialization protected Object untrace(VirtualFrame frame, Object whatObj, Object signature, Object whereObj) { Object what = whatObj; - checkWhat(what); + helper.checkWhat(what); Object where = whereObj; if (where == RMissing.instance) { - where = getWhere(frame); + where = helper.getWhere(frame); } String funcName = RRuntime.asString(what); if (funcName != null) { - what = getFunction(frame, what, where); + what = helper.getFunction(frame, what, where); } - RFunction func = checkFunction(what); + RFunction func = helper.checkFunction(what); if (signature == RMissing.instance) { if (primUnTrace == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); primUnTrace = insert(PrimUnTraceNodeGen.create()); } - primUnTrace.executeBuiltin(frame, func); + primUnTrace.execute(frame, func); } else { throw RError.nyi(this, "method tracing"); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTree.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTree.java index 7071bb26a0b839e61a49f0997f1738cff88abfd1..85284f52cdfba70b385777f05b68bebe11bcab2c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTree.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTree.java @@ -39,7 +39,7 @@ import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RMissing; @RBuiltin(name = ".fastr.tree", visibility = OFF, kind = PRIMITIVE, parameterNames = {"func", "verbose"}, behavior = IO) -public abstract class FastRTree extends RBuiltinNode { +public abstract class FastRTree extends RBuiltinNode.Arg2 { @Override public Object[] getDefaultParameterValues() { return new Object[]{RMissing.instance, RRuntime.LOGICAL_FALSE}; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTreeStats.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTreeStats.java index 968cf379a3f1aea483d9fe70459b4a1dd4aa4265..75a82d67668729717c7458700c24757ba51b08f8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTreeStats.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTreeStats.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.builtin.fastr; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -38,7 +39,6 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; 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.RStringVector; @@ -46,13 +46,13 @@ import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RBaseNode; @RBuiltin(name = ".fastr.treestats", kind = PRIMITIVE, parameterNames = {"obj"}, behavior = COMPLEX) -public abstract class FastRTreeStats extends RBuiltinNode { +public abstract class FastRTreeStats extends RBuiltinNode.Arg1 { private static final RStringVector COLNAMES = RDataFactory.createStringVector(new String[]{"Total", "Syntax", "Non-Syntax"}, RDataFactory.COMPLETE_VECTOR); - @Override - public Object[] getDefaultParameterValues() { - return new Object[]{RMissing.instance}; + static { + Casts casts = new Casts(FastRTreeStats.class); + casts.arg("obj").allowNull().mustBe(instanceOf(REnvironment.class).or(instanceOf(RFunction.class))); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTry.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTry.java index 45a57b19326df2fafe3f82f8218977900929712a..53cf1f0e42896f1d33eff6993c57d6e7d8427cb7 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTry.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTry.java @@ -41,7 +41,7 @@ import com.oracle.truffle.r.runtime.data.RFunction; * message. */ @RBuiltin(name = ".fastr.try", kind = PRIMITIVE, parameterNames = {""}, behavior = COMPLEX) -public abstract class FastRTry extends RBuiltinNode { +public abstract class FastRTry extends RBuiltinNode.Arg1 { @Child private RExplicitCallNode call = RExplicitCallNode.create(); static { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java index fb4cc5a0b3a335acb99cdb2b2f0eb05b781063c2..043cfb754430f72f058c3e9b69e9990ea807fee0 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java @@ -11,6 +11,8 @@ */ package com.oracle.truffle.r.nodes.builtin.fastr; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.runtime.RVisibility.OFF; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -36,21 +38,21 @@ import com.oracle.truffle.r.runtime.ffi.RFFIFactory; * directly this Fortran routine. */ @RBuiltin(name = ".fastr.dqrls", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x", "n", "p", "y", "ny", "tol", "coeff"}, behavior = PURE) -public abstract class FastrDqrls extends RBuiltinNode { - @Child private RApplRFFI.RApplRFFINode rApplRFFINode = RFFIFactory.getRFFI().getRApplRFFI().createRApplRFFINode(); +public abstract class FastrDqrls extends RBuiltinNode.Arg7 { + @Child private RApplRFFI.DqrlsNode dqrlsNode = RFFIFactory.getRFFI().getRApplRFFI().createDqrlsNode(); private static final String[] NAMES = new String[]{"qr", "coefficients", "residuals", "effects", "rank", "pivot", "qraux", "tol", "pivoted"}; private static RStringVector namesVector = null; static { Casts casts = new Casts(FastrDqrls.class); - casts.arg("x").asDoubleVector(true, true, true); + casts.arg("x").mustNotBeMissing().mustNotBeNull().asDoubleVector(true, true, true); casts.arg("n").asIntegerVector().findFirst(); casts.arg("p").asIntegerVector().findFirst(); - casts.arg("y").asDoubleVector(true, true, true); + casts.arg("y").mustNotBeMissing().mustNotBeNull().asDoubleVector(true, true, true); casts.arg("ny").asIntegerVector().findFirst(); casts.arg("tol").asDoubleVector().findFirst(); - casts.arg("coeff").asDoubleVector(true, true, true); + casts.arg("coeff").mustNotBeMissing().mustNotBeNull().asDoubleVector(true, true, true); } @@ -61,7 +63,7 @@ public abstract class FastrDqrls extends RBuiltinNode { @Specialization(replaces = "doDouble") public RList doOther(RAbstractVector xVec, int n, int p, RAbstractVector yVec, int ny, double tol, RAbstractDoubleVector coeffVec, @Cached(value = "create()") CastDoubleNode castNode) { - return call(xVec, ((RAbstractDoubleVector) castNode.execute(xVec)).materialize(), n, p, yVec, ((RAbstractDoubleVector) castNode.execute(yVec)).materialize(), ny, tol, coeffVec); + return call(xVec, ((RAbstractDoubleVector) castNode.doCast(xVec)).materialize(), n, p, yVec, ((RAbstractDoubleVector) castNode.doCast(yVec)).materialize(), ny, tol, coeffVec); } private RList call(RAbstractVector originalXVec, RDoubleVector xVec, int n, int p, RAbstractVector originalYVec, RDoubleVector yVec, int ny, double tol, RAbstractDoubleVector coeffVec) { @@ -78,7 +80,7 @@ public abstract class FastrDqrls extends RBuiltinNode { pivot[i] = i + 1; } - rApplRFFINode.dqrls(x, n, p, y, ny, tol, coeff, residuals, effects, rank, pivot, qraux, work); + dqrlsNode.execute(x, n, p, y, ny, tol, coeff, residuals, effects, rank, pivot, qraux, work); RDoubleVector resultCoeffVect = RDataFactory.createDoubleVector(coeff, RDataFactory.COMPLETE_VECTOR); resultCoeffVect.copyAttributesFrom(coeffVec); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java index 78c4fd48204f108f6fb44bc9d9ff2eaa70ff7f1c..71c6062bdd2008f75dcd907869329f567c527a8c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.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 @@ -154,6 +154,7 @@ public abstract class BrowserInteractNode extends RNode { } catch (IncompleteSourceException e) { // read another line of input ch.setPrompt("+ "); + sb.append('\n'); sb.append(ch.readLine()); // The only continuation in the while loop continue; 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 80f96d66aa3d6895cfc9aee862ccb5d78126473b..75684febae6ee8df37d7d1fd758169b6a918569f 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 @@ -45,6 +45,7 @@ import com.oracle.truffle.r.nodes.control.AbstractLoopNode; import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; import com.oracle.truffle.r.nodes.instrumentation.RInstrumentation; import com.oracle.truffle.r.nodes.instrumentation.RSyntaxTags; +import com.oracle.truffle.r.runtime.JumpToTopLevelException; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.RError; @@ -186,17 +187,18 @@ public class DebugHandling { @Override protected Void visit(RSyntaxFunction element) { + accept(element.getSyntaxBody()); return null; } }.accept(fdn); return fser; } - private static void ensureSingleStep(FunctionDefinitionNode fdn) { + private static FunctionStatementsEventListener ensureSingleStep(FunctionDefinitionNode fdn) { FunctionStatementsEventListener fser = getFunctionStatementsEventListener(fdn); if (fser == null) { // attach a "once" listener - fser = attachDebugHandler(fdn, null, null, true, false); + fser = attachDebugHandler(fdn, null, null, true, true); } else { if (fser.disabled()) { fser.enable(); @@ -204,6 +206,7 @@ public class DebugHandling { fser.enabledForStepInto = true; } } + return fser; } private abstract static class DebugEventListener implements ExecutionEventListener { @@ -293,8 +296,9 @@ public class DebugHandling { @TruffleBoundary private void attachStepInto() { - stepIntoInstrument = RInstrumentation.getInstrumenter().attachListener(SourceSectionFilter.newBuilder().tagIs(StandardTags.RootTag.class).build(), - new StepIntoInstrumentListener(getFunctionStatementsEventListener(functionDefinitionNode))); + FunctionStatementsEventListener parentListener = getFunctionStatementsEventListener(functionDefinitionNode); + parentListener.stepIntoInstrument = RInstrumentation.getInstrumenter().attachListener(SourceSectionFilter.newBuilder().tagIs(StandardTags.RootTag.class).build(), + new StepIntoInstrumentListener(parentListener)); } @@ -426,7 +430,7 @@ public class DebugHandling { public void onReturnValue(EventContext context, VirtualFrame frame, Object result) { if (!disabled()) { CompilerDirectives.transferToInterpreter(); - returnCleanup(frame); + returnCleanup(frame, false); } } @@ -434,12 +438,12 @@ public class DebugHandling { public void onReturnExceptional(EventContext context, VirtualFrame frame, Throwable exception) { if (!disabled()) { CompilerDirectives.transferToInterpreter(); - returnCleanup(frame); + returnCleanup(frame, exception instanceof JumpToTopLevelException); } } - private void returnCleanup(VirtualFrame frame) { - if (!implicit) { + private void returnCleanup(VirtualFrame frame, boolean jumpToTopLevel) { + if (!implicit && !once && !jumpToTopLevel) { print("exiting from: ", false); printCall(frame); } @@ -502,7 +506,7 @@ public class DebugHandling { return; } printNode(node, false); - browserInteract(context.getInstrumentedNode(), frame); + browserInteract(node, frame); } } @@ -511,6 +515,9 @@ public class DebugHandling { } } + /** + * Handles the loop header and there is one instance registered for each loop. + */ private static class LoopStatementEventListener extends StatementEventListener { private boolean finishing; @@ -529,7 +536,7 @@ public class DebugHandling { @Override public void onEnter(EventContext context, VirtualFrame frame) { - if (!disabled()) { + if (!disabled() && context.getInstrumentedNode() == loopNode) { super.onEnter(context, frame); } } @@ -544,7 +551,7 @@ public class DebugHandling { @Override public void onReturnExceptional(EventContext context, VirtualFrame frame, Throwable exception) { - if (!disabled()) { + if (!disabled() && context.getInstrumentedNode() == loopNode) { CompilerDirectives.transferToInterpreter(); returnCleanup(); } @@ -552,7 +559,7 @@ public class DebugHandling { @Override public void onReturnValue(EventContext context, VirtualFrame frame, Object result) { - if (!disabled()) { + if (!disabled() && context.getInstrumentedNode() == loopNode) { CompilerDirectives.transferToInterpreter(); returnCleanup(); } @@ -592,9 +599,10 @@ public class DebugHandling { if (!RContext.getInstance().stateInstrumentation.debugGloballyDisabled()) { CompilerDirectives.transferToInterpreter(); FunctionDefinitionNode fdn = (FunctionDefinitionNode) context.getInstrumentedNode().getRootNode(); - ensureSingleStep(fdn); + FunctionStatementsEventListener ensureSingleStep = ensureSingleStep(fdn); + functionStatementsEventListener.clearStepInstrument(); - functionStatementsEventListener.onEnter(context, frame); + ensureSingleStep.onEnter(context, frame); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java index 7b85116832f9cdf20d51f6aca30920ca7b9f7869..c7e0be6ae92111eef9d4f595660328e6f1df8434 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.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 @@ -148,7 +148,7 @@ public class TraceHandling { protected String getCallSource(VirtualFrame frame) { RCaller caller = RArguments.getCall(frame); String callString; - if (caller != null) { + if (caller != null && caller.isValidCaller()) { callString = getCallerSource(caller); } else { callString = "<no source>"; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/methods/R/methods_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/methods/R/methods_overrides.R new file mode 100644 index 0000000000000000000000000000000000000000..99c947a62dbc8ce4e07359f7873abf9baab63558 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/methods/R/methods_overrides.R @@ -0,0 +1,26 @@ +# 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. + +eval(expression({ +# this function is replaced with a primitive because it is expected to +# modify its argument in-place, which can clash with argument refcount handling +`slot<-` <- .fastr.methods.slotassign +}), asNamespace("methods")) 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 42d5c9ce8b44849166eb70e73832f781475e471e..2d3ebf6b49a58ea052b43953b3c3e1c47aaaad39 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 @@ -11,22 +11,35 @@ ## Derived from snow and parallel packages -eval(expression( +eval(expression({ + +# overwritten functions: + +makeCluster <- function (spec, type = getClusterOption("type"), ...) { + switch(type, + PSOCK = makePSOCKcluster(spec, ...), + FORK = makeForkCluster(spec, ...), + SOCK = snow::makeSOCKcluster(spec, ...), + MPI = snow::makeMPIcluster(spec, ...), + NWS = snow::makeNWScluster(spec, ...), + SHARED = makeSHAREDcluster(spec, ...), # this line was added + stop("unknown cluster type")) +} + +# added functions: + closeNode.SHAREDnode <- function(node) { .fastr.channel.close(node$channel) -}), asNamespace("parallel")) +} -eval(expression( sendData.SHAREDnode <- function(node, data) { .fastr.channel.send(node$channel, data) -}), asNamespace("parallel")) +} -eval(expression( recvData.SHAREDnode <- function(node) { .fastr.channel.receive(node$channel) -}), asNamespace("parallel")) +} -eval(expression( recvOneData.SHAREDcluster <- function(cl) { channel_ids = lapply(cl, function(l) l[["channel"]]) res <- .fastr.channel.select(channel_ids) @@ -35,57 +48,67 @@ recvOneData.SHAREDcluster <- function(cl) { indexes = lapply(cl, function(l, id) if (identical(l[["channel"]], id)) id else as.integer(NA), id=selected_id) node_ind = which(as.double(indexes)==as.double(selected_id)) list(node = node_ind, value = res[[2]]) -}), asNamespace("parallel")) - -eval(expression( -fastr.newSHAREDnode <- function(rank, options = defaultClusterOptions) -{ - # Add the "debug" option defaulted to FALSE, if the user didn't specify - # If the user gives TRUE, print extra stuff during cluster setup - debug <- FALSE - tryCatch( - debug <- parallel:::getClusterOption("debug", options), - error = function(e) { } - ) - options <- parallel:::addClusterOptions(options, list(debug = debug)) +} - # generate unique values for channel keys (addition factor is chosen based on how snow generates port numbers) - port <- as.integer(parallel:::getClusterOption("port", options) + rank * 1000) - script <- file.path(R.home(), "com.oracle.truffle.r.native", "library", "parallel", "RSHAREDnode.R") +newSHAREDnodes <- function(nnodes, debug, options = defaultClusterOptions) { + context_code <- vector("character", nnodes) + contexts <- vector("integer", nnodes) + channels <- vector("integer", nnodes) + outfile <- getClusterOption("outfile", options) + for (i in 1:nnodes) { + # generate unique values for channel keys (addition factor is chosen based on how snow generates port numbers) + port <- as.integer(parallel:::getClusterOption("port", options) + i * 1000) + + startup <- substitute(local({ + makeSHAREDmaster <- function(key) { + channel <- .fastr.channel.get(as.integer(key)) + structure(list(channel=channel), class = "SHAREDnode") + } + parallel:::sinkWorkerOutput(OUTFILE) + parallel:::slaveLoop(makeSHAREDmaster(PORT)) + }), list(OUTFILE=outfile, PORT=port)) + + context_code[[i]] <- paste0(deparse(startup), collapse="\n") + if (isTRUE(debug)) cat(sprintf("Starting context: %d with code %s\n", i, context_code[[i]])) - context_code <- paste0("commandArgs<-function() c('--args', 'PORT=", port, "'); source('", script, "')") - if (isTRUE(debug)) cat(sprintf("Starting context: %d with code %s\n", rank, context_code)) - - cx <- .fastr.context.spawn(context_code) - - ## Need to return a list here, in the same form as the - ## "cluster" data structure. - channel <- .fastr.channel.create(port) - if (isTRUE(debug)) cat(sprintf("Context %d started!\n", rank)) - structure(list(channel = channel, context=cx, rank = rank), class = "SHAREDnode") -}), asNamespace("parallel")) + ## Need to return a list here, in the same form as the + ## "cluster" data structure. + channels[[i]] <- .fastr.channel.create(port) + if (isTRUE(debug)) cat(sprintf("Context %d started!\n", i)) + } + contexts <- .fastr.context.spawn(context_code) + cl <- vector("list", nnodes) + for (i in 1:nnodes) { + cl[[i]] <- structure(list(channel = channels[[i]], context=contexts[[i]], rank = i), class = "SHAREDnode") + } + cl +} -makeForkClusterExpr <- expression({ -makeForkCluster <- function(nnodes = getOption("mc.cores", 2L), options = defaultClusterOptions, ...) -{ +makeSHAREDcluster <- function(nnodes = getOption("mc.cores", 2L), options = defaultClusterOptions, ...) { nnodes <- as.integer(nnodes) if(is.na(nnodes) || nnodes < 1L) stop("'nnodes' must be >= 1") .check_ncores(nnodes) options <- addClusterOptions(options, list(...)) - cl <- vector("list", nnodes) - for (i in seq_along(cl)) cl[[i]] <- fastr.newSHAREDnode(rank=i, options=options) + + # Add the "debug" option defaulted to FALSE, if the user didn't specify + # If the user gives TRUE, print extra stuff during cluster setup + debug <- FALSE + if (exists("debug", envir=options, inherits=FALSE)) { + debug <- parallel:::getClusterOption("debug", options) + } else { + options <- parallel:::addClusterOptions(options, list(debug = debug)) + } + + cl <- newSHAREDnodes(nnodes, debug = debug, options=options) class(cl) <- c("SHAREDcluster", "cluster") cl -}; environment(makeForkCluster)<-asNamespace("parallel")}) -eval(makeForkClusterExpr, asNamespace("parallel")) -# seems like we don't need these anymore, but let's make sure -#eval(makeForkClusterExpr, as.environment("package:parallel")) - +} -eval(expression( stopCluster.SHAREDcluster <- function(cl) { for (n in cl) { parallel:::postNode(n, "DONE") .fastr.context.join(n$context) } +} + }), asNamespace("parallel")) diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ArgumentFilterSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ArgumentFilterSampler.java deleted file mode 100644 index 6132d830f6ec9e0059ba08ee26b8d1cf5cc631df..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ArgumentFilterSampler.java +++ /dev/null @@ -1,339 +0,0 @@ -/* - * 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 - * 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.casts; - -import com.oracle.truffle.r.nodes.builtin.ArgumentFilter; - -public interface ArgumentFilterSampler<T, R> extends ArgumentFilter<T, R> { - - Samples<R> collectSamples(TypeExpr inputType); - - TypeExpr trueBranchType(); - - TypeExpr falseBranchType(); - - interface NarrowingArgumentFilterSampler<T, R extends T> extends NarrowingArgumentFilter<T, R>, ArgumentFilterSampler<T, R> { - - @Override - default <S extends T> ArgumentTypeFilterSampler<T, T> or(ArgumentFilter<T, S> o) { - final ArgumentFilterSampler<T, S> other = (ArgumentFilterSampler<T, S>) o; - - return new ArgumentTypeFilterSampler<T, T>() { - - @Override - public boolean test(T arg) { - if (NarrowingArgumentFilterSampler.this.test(arg)) { - return true; - } else { - return other.test(arg); - } - } - - @Override - public TypeExpr trueBranchType() { - return NarrowingArgumentFilterSampler.this.trueBranchType().or(other.trueBranchType()); - } - - @Override - public Samples<T> collectSamples(TypeExpr inputType) { - Samples<R> thisSamples = NarrowingArgumentFilterSampler.this.collectSamples(inputType); - Samples<S> otherSamples = other.collectSamples(inputType); - return Samples.<T> anything().and(thisSamples).or(otherSamples); - } - }; - } - } - - interface ArgumentValueFilterSampler<T> extends ArgumentValueFilter<T>, NarrowingArgumentFilterSampler<T, T> { - - @Override - default TypeExpr falseBranchType() { - this.or(null); - return trueBranchType(); - } - - @Override - default <S extends T> ArgumentValueFilterSampler<T> or(ArgumentValueFilter<T> o) { - final ArgumentValueFilterSampler<T> other = (ArgumentValueFilterSampler<T>) o; - - return new ArgumentValueFilterSampler<T>() { - - @Override - public boolean test(T arg) { - if (ArgumentValueFilterSampler.this.test(arg)) { - return true; - } else { - return other.test(arg); - } - } - - @Override - public TypeExpr trueBranchType() { - return ArgumentValueFilterSampler.this.trueBranchType().or(other.trueBranchType()); - } - - @Override - public Samples<T> collectSamples(TypeExpr inputType) { - Samples<T> thisSamples = ArgumentValueFilterSampler.this.collectSamples(inputType); - Samples<T> otherSamples = other.collectSamples(inputType); - return Samples.<T> anything().and(thisSamples).or(otherSamples); - } - }; - } - - @Override - default ArgumentValueFilterSampler<T> and(ArgumentValueFilter<T> o) { - final ArgumentValueFilterSampler<T> other = (ArgumentValueFilterSampler<T>) o; - - return new ArgumentValueFilterSampler<T>() { - - @Override - public boolean test(T arg) { - return ArgumentValueFilterSampler.this.test(arg) && other.test(arg); - } - - @Override - public TypeExpr trueBranchType() { - return ArgumentValueFilterSampler.this.trueBranchType().and(other.trueBranchType()); - } - - @Override - public Samples<T> collectSamples(TypeExpr inputType) { - Samples<T> thisSamples = ArgumentValueFilterSampler.this.collectSamples(inputType); - Samples<T> otherSamples = other.collectSamples(inputType); - - return thisSamples.and(otherSamples); - } - }; - } - - @Override - default <S extends T> ArgumentTypeFilterSampler<T, S> and(ArgumentTypeFilter<T, S> o) { - final ArgumentTypeFilterSampler<T, S> other = (ArgumentTypeFilterSampler<T, S>) o; - - return new ArgumentTypeFilterSampler<T, S>() { - - @Override - public boolean test(T arg) { - return ArgumentValueFilterSampler.this.test(arg) && other.test(arg); - } - - @Override - public TypeExpr trueBranchType() { - return ArgumentValueFilterSampler.this.trueBranchType().and(other.trueBranchType()); - } - - @SuppressWarnings("unchecked") - @Override - public Samples<S> collectSamples(TypeExpr inputType) { - Samples<T> thisSamples = ArgumentValueFilterSampler.this.collectSamples(inputType); - Samples<S> otherSamples = other.collectSamples(inputType); - - return (Samples<S>) thisSamples.and(otherSamples); - } - }; - } - - @Override - default ArgumentValueFilterSampler<T> not() { - return new ArgumentValueFilterSampler<T>() { - - @Override - public boolean test(T arg) { - return !ArgumentValueFilterSampler.this.test(arg); - } - - @Override - public TypeExpr trueBranchType() { - return ArgumentValueFilterSampler.this.trueBranchType(); - } - - @SuppressWarnings("unchecked") - @Override - public Samples<T> collectSamples(TypeExpr inputType) { - Samples<T> thisSamples = ArgumentValueFilterSampler.this.collectSamples(inputType); - return (Samples<T>) thisSamples.swap(); - } - }; - } - } - - interface ArgumentTypeFilterSampler<T, R extends T> extends ArgumentTypeFilter<T, R>, NarrowingArgumentFilterSampler<T, R> { - - @Override - default TypeExpr falseBranchType() { - return trueBranchType().not(); - } - - @Override - default <S extends R> ArgumentTypeFilterSampler<T, S> and(ArgumentTypeFilter<R, S> o) { - final ArgumentTypeFilterSampler<R, S> other = (ArgumentTypeFilterSampler<R, S>) o; - - return new ArgumentTypeFilterSampler<T, S>() { - - @SuppressWarnings("unchecked") - @Override - public boolean test(T arg) { - return ArgumentTypeFilterSampler.this.test(arg) && other.test((R) arg); - } - - @Override - public TypeExpr trueBranchType() { - return ArgumentTypeFilterSampler.this.trueBranchType().and(other.trueBranchType()); - } - - @SuppressWarnings("unchecked") - @Override - public Samples<S> collectSamples(TypeExpr inputType) { - Samples<R> thisSamples = ArgumentTypeFilterSampler.this.collectSamples(inputType); - Samples<S> otherSamples = other.collectSamples(inputType); - - return (Samples<S>) thisSamples.and(otherSamples); - } - }; - } - - @Override - default ArgumentTypeFilter<T, R> and(ArgumentValueFilter<R> o) { - final ArgumentValueFilterSampler<R> other = (ArgumentValueFilterSampler<R>) o; - - return new ArgumentTypeFilterSampler<T, R>() { - - @SuppressWarnings("unchecked") - @Override - public boolean test(T arg) { - return ArgumentTypeFilterSampler.this.test(arg) && other.test((R) arg); - } - - @Override - public TypeExpr trueBranchType() { - return ArgumentTypeFilterSampler.this.trueBranchType().and(other.trueBranchType()); - } - - @Override - public Samples<R> collectSamples(TypeExpr inputType) { - Samples<R> thisSamples = ArgumentTypeFilterSampler.this.collectSamples(inputType); - Samples<R> otherSamples = other.collectSamples(inputType); - - return otherSamples.and(thisSamples); - } - }; - } - - @Override - default InverseArgumentFilterSampler<T, R> not() { - return new InverseArgumentFilterSampler<>(this); - } - } - - class InverseArgumentFilterSampler<T, R extends T> extends InverseArgumentFilter<T, R> implements ArgumentFilterSampler<T, Object> { - - private final ArgumentTypeFilterSampler<T, R> orig; - - public InverseArgumentFilterSampler(ArgumentTypeFilter<T, R> o) { - super(o); - this.orig = (ArgumentTypeFilterSampler<T, R>) o; - } - - @Override - public TypeExpr trueBranchType() { - return orig.trueBranchType().not(); - } - - @Override - public TypeExpr falseBranchType() { - return orig.falseBranchType().not(); - } - - @Override - public Samples<Object> collectSamples(TypeExpr inputType) { - Samples<? extends R> thisSamples = orig.collectSamples(inputType); - return thisSamples.swap(); - } - - @Override - public ArgumentTypeFilterSampler<T, R> not() { - return orig; - } - - @Override - public <S extends T> ArgumentTypeFilterSampler<T, S> and(ArgumentTypeFilter<T, S> o) { - final ArgumentTypeFilterSampler<T, S> other = (ArgumentTypeFilterSampler<T, S>) o; - - return new ArgumentTypeFilterSampler<T, S>() { - - @Override - public boolean test(T arg) { - return InverseArgumentFilterSampler.this.test(arg) && other.test(arg); - } - - @Override - public TypeExpr trueBranchType() { - return InverseArgumentFilterSampler.this.trueBranchType().and(other.trueBranchType()); - } - - @SuppressWarnings("unchecked") - @Override - public Samples<S> collectSamples(TypeExpr inputType) { - Samples<Object> thisSamples = InverseArgumentFilterSampler.this.collectSamples(inputType); - Samples<S> otherSamples = other.collectSamples(inputType); - - return (Samples<S>) thisSamples.and(otherSamples); - } - }; - } - - @Override - public <S extends T> ArgumentValueFilterSampler<S> and(ArgumentValueFilter<S> o) { - final ArgumentValueFilterSampler<S> other = (ArgumentValueFilterSampler<S>) o; - - return new ArgumentValueFilterSampler<S>() { - - @Override - public boolean test(S arg) { - return InverseArgumentFilterSampler.this.test(arg) && other.test(arg); - } - - @Override - public TypeExpr trueBranchType() { - return InverseArgumentFilterSampler.this.trueBranchType().and(other.trueBranchType()); - } - - @SuppressWarnings("unchecked") - @Override - public Samples<S> collectSamples(TypeExpr inputType) { - Samples<Object> thisSamples = InverseArgumentFilterSampler.this.collectSamples(inputType); - Samples<S> otherSamples = other.collectSamples(inputType); - - return (Samples<S>) thisSamples.and(otherSamples); - } - }; - } - - @Override - public <S extends T> InverseArgumentFilterSampler<T, T> and(InverseArgumentFilter<T, S> o) { - InverseArgumentFilterSampler<T, S> other = (InverseArgumentFilterSampler<T, S>) o; - return new InverseArgumentFilterSampler<>(other.orig.or(this.orig)); - } - } -} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastNodeSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastNodeSampler.java deleted file mode 100644 index 880cfb0c9a140e3b70e4be958e3c501d3c4d50ed..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastNodeSampler.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 - * 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.casts; - -import java.lang.reflect.Constructor; -import java.util.LinkedList; -import java.util.List; - -import com.oracle.truffle.r.nodes.unary.CastNode; - -public class CastNodeSampler<T extends CastNode> { - - protected final T castNode; - - public CastNodeSampler(T castNode) { - this.castNode = castNode; - } - - public T getCastNode() { - return castNode; - } - - public final TypeExpr resultTypes() { - SamplingContext ctx = new SamplingContext(); - TypeExpr resTypes = resultTypes(TypeExpr.ANYTHING, ctx); - for (TypeExpr altResType : ctx.altResultTypes) { - resTypes = resTypes.or(altResType); - } - return resTypes; - } - - public TypeExpr resultTypes(TypeExpr inputType, SamplingContext ctx) { - return CastUtils.Casts.createCastNodeCasts(castNode.getClass().getSuperclass()).narrow(inputType); - } - - public final Samples<?> collectSamples() { - return collectSamples(TypeExpr.ANYTHING, Samples.anything()); - } - - @SuppressWarnings("unused") - public Samples<?> collectSamples(TypeExpr inputType, Samples<?> downStreamSamples) { - return downStreamSamples; - } - - public static <T extends CastNode> CastNodeSampler<T> createSampler(T castNode) { - return createSampler(castNode, true); - } - - @SuppressWarnings("unchecked") - public static <T extends CastNode> CastNodeSampler<T> createSampler(T castNode, boolean useDefaultSampler) { - if (castNode == null) { - return null; - } - - Class<? extends CastNode> castNodeCls = castNode.getClass(); - String clsName = castNodeCls.getName(); - String analyzerClsName = clsName + "Sampler"; - Class<?> analyzerCls; - try { - analyzerCls = Class.forName(analyzerClsName); - } catch (ClassNotFoundException e) { - if (useDefaultSampler) { - return new CastNodeSampler<>(castNode); - } else { - throw new IllegalArgumentException("No sampler class found for cast node " + clsName); - } - } - - try { - Constructor<?> analyzerConstr = analyzerCls.getConstructor(castNodeCls); - return (CastNodeSampler<T>) analyzerConstr.newInstance(castNode); - } catch (Exception e) { - throw new IllegalArgumentException(e); - } - } - - public static final class SamplingContext { - private List<TypeExpr> altResultTypes = new LinkedList<>(); - - public void addAltResultType(TypeExpr altResType) { - altResultTypes.add(altResType); - } - } -} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java index 58c4a898ee8cb144c1eab078be85446f5e0af998..0b68e310c4c02f17aa36a82d62c5418da65a652f 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java @@ -38,17 +38,20 @@ import java.util.stream.Collectors; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RListBase; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RRaw; import com.oracle.truffle.r.runtime.data.RTypes; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; 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.RAbstractLogicalVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -250,6 +253,15 @@ public class CastUtils { } }; + /** + * It transforms this type coverage into another one that would be returned in the + * situation when the source and the target type were either positive or negative, as + * determined by the <code>sourcePositive</code> and <code>targetPositive</code> + * arguments. + * <p> + * N.B. It is assumed that this coverage is obtained for the positive source anb target + * types. + */ public abstract Coverage transpose(Type sourceType, Type targetType, boolean sourcePositive, boolean targetPositive); public abstract Coverage or(Coverage other); @@ -333,14 +345,14 @@ public class CastUtils { } public static Set<Cast> findConvertibleActualType(TypeExpr actualInputTypes, Type formalInputCls, boolean includeImplicits) { - Set<Type> normActTypes = actualInputTypes.normalize(); + Set<Type> normActTypes = actualInputTypes.toNormalizedConjunctionSet(); return normActTypes.stream().map(actualInputCls -> new Cast(actualInputCls, formalInputCls, isConvertible(actualInputCls, formalInputCls, includeImplicits))).filter( c -> c.coverage != Cast.Coverage.none).collect(Collectors.toSet()); } public static Cast.Coverage isConvertible(Type actualInputType, Type formalInputType, boolean includeImplicits) { - TypeConjunction from = TypeConjunction.fromType(actualInputType); - TypeConjunction to = TypeConjunction.fromType(formalInputType); + UpperBoundsConjunction from = UpperBoundsConjunction.fromType(actualInputType); + UpperBoundsConjunction to = UpperBoundsConjunction.fromType(formalInputType); Cast.Coverage result = to.coverageFrom(from, includeImplicits); return result; @@ -415,12 +427,12 @@ public class CastUtils { if (argTypeSets.isEmpty()) { return Collections.emptySet(); } else if (argTypeSets.size() == 1) { - return argTypeSets.get(0).normalize().stream().map((Type t) -> Collections.singletonList(t)).collect(Collectors.toSet()); + return argTypeSets.get(0).toNormalizedConjunctionSet().stream().map((Type t) -> Collections.singletonList(t)).collect(Collectors.toSet()); } else { Set<List<Type>> tailPowerSet = argumentProductSet(argTypeSets.subList(1, argTypeSets.size())); TypeExpr headArgSet = argTypeSets.get(0); Set<List<Type>> resultSet = new HashSet<>(); - for (Type headType : headArgSet.normalize()) { + for (Type headType : headArgSet.toNormalizedConjunctionSet()) { Set<LinkedList<Type>> extSublists = tailPowerSet.stream().map(x -> { LinkedList<Type> extSublist = new LinkedList<>(x); extSublist.addFirst(headType); @@ -461,13 +473,16 @@ public class CastUtils { if (RAbstractComplexVector.class.isAssignableFrom(vectorType) || RComplex.class.isAssignableFrom(vectorType)) { return RComplex.class; } + if (RAbstractRawVector.class.isAssignableFrom(vectorType)) { + return RRaw.class; + } if (RListBase.class.isAssignableFrom(vectorType)) { return Object.class; } - if (RAbstractVector.class.isAssignableFrom(vectorType) || vectorType == Object.class) { - return Not.negateType(RAbstractVector.class); + if (RAbstractVector.class.isAssignableFrom(vectorType)) { + return Object.class; } - return Not.negateType(RAbstractVector.class); + return vectorType; } public static RAbstractVector emptyVector(Class<?> elementType) { @@ -514,6 +529,81 @@ public class CastUtils { return null; } + public static RAbstractVector vectorOfSize(RType vectorType, int size) { + switch (vectorType) { + case Integer: + return RDataFactory.createIntVector(size); + case Double: + return RDataFactory.createDoubleVector(size); + case Logical: + return RDataFactory.createLogicalVector(size); + case Character: + return RDataFactory.createStringVector(size); + case Complex: + return RDataFactory.createComplexVector(size); + case Any: + return RDataFactory.createIntVector(size); + default: + return null; + } + } + + @SuppressWarnings("rawtypes") + public static Class<?>[] rTypeToClasses(RType type) { + switch (type) { + case Integer: + return new Class[]{Integer.class, RAbstractIntVector.class}; + case Double: + return new Class[]{Double.class, RAbstractDoubleVector.class}; + case Logical: + return new Class[]{Byte.class, RAbstractLogicalVector.class}; + case Character: + return new Class[]{String.class, RAbstractStringVector.class}; + case Complex: + return new Class[]{RAbstractComplexVector.class}; + case Raw: + return new Class[]{RAbstractRawVector.class}; + case Any: + return new Class[]{Object.class}; + } + return null; + } + + public static RAbstractVector fillVector(RType vectorType, int size, Object value, boolean complete) { + switch (vectorType) { + case Integer: + int[] iarray = new int[size]; + Arrays.fill(iarray, (int) value); + return RDataFactory.createIntVector(iarray, complete); + case Double: + double[] darray = new double[size]; + Arrays.fill(darray, (double) value); + return RDataFactory.createDoubleVector(darray, complete); + case Logical: + byte[] larray = new byte[size]; + Arrays.fill(larray, (byte) value); + return RDataFactory.createLogicalVector(larray, complete); + case Character: + String[] sarray = new String[size]; + Arrays.fill(sarray, value); + return RDataFactory.createStringVector(sarray, complete); + case Complex: + double[] carray = new double[2 * size]; + RComplex c = (RComplex) value; + for (int i = 0; i < size; i++) { + carray[2 * i] = c.getRealPart(); + carray[2 * i + 1] = c.getImaginaryPart(); + } + return RDataFactory.createComplexVector(carray, complete); + case Any: + Object[] oarray = new Object[size]; + Arrays.fill(oarray, value); + return RDataFactory.createList(oarray); + default: + return null; + } + } + public static Object naVector(Class<?> elementType) { if (Integer.class.isAssignableFrom(elementType)) { return RDataFactory.createIntVectorFromScalar(RRuntime.INT_NA); @@ -660,13 +750,18 @@ public class CastUtils { } public static Set<?> sampleValuesForTypeExpr(TypeExpr te) { - return te.normalize().stream().flatMap(t -> CastUtils.sampleValuesForType(t).stream()).collect(Collectors.toSet()); + return te.toNormalizedConjunctionSet().stream().flatMap(t -> CastUtils.sampleValuesForType(t).stream()).collect(Collectors.toSet()); } - public static Set<?> sampleValuesForClases(Class<?>[] classes) { + public static Set<?> sampleValuesForClasses(Class<?>[] classes) { return Arrays.stream(classes).flatMap(t -> CastUtils.sampleValuesForType(t).stream()).collect(Collectors.toSet()); } + @SuppressWarnings("rawtypes") + public static Set<?> sampleValuesForClass(Class<?> cls) { + return sampleValuesForClasses(new Class[]{cls}); + } + public static Set<?> sampleValuesForType(Type t) { HashSet<Object> samples = new HashSet<>(); @@ -734,6 +829,8 @@ public class CastUtils { } if (cls == Object.class || RAbstractComplexVector.class.isAssignableFrom(cls)) { + samples.add(RComplex.createNA()); + samples.add(RDataFactory.createComplex(0, 0)); samples.add(RDataFactory.createComplexVectorFromScalar(RComplex.valueOf(0, 0))); samples.add(RDataFactory.createComplexVectorFromScalar(RComplex.valueOf(1, 1))); samples.add(RDataFactory.createComplexVectorFromScalar(RComplex.valueOf(-1, 1))); @@ -747,6 +844,7 @@ public class CastUtils { if (cls == Object.class || String.class.isAssignableFrom(cls)) { samples.add(""); samples.add("abc"); + samples.add(RRuntime.STRING_NA); } if (cls == Object.class || RAbstractStringVector.class.isAssignableFrom(cls)) { @@ -757,6 +855,11 @@ public class CastUtils { samples.add(RDataFactory.createStringVector(new String[]{RRuntime.STRING_NA}, false)); } + if (RAbstractRawVector.class.isAssignableFrom(cls)) { + samples.add((byte) 0); + samples.add(RDataFactory.createRawVector(new byte[]{0})); + } + samples.remove(null); return samples; diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/FilterSamplerFactory.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/FilterSamplerFactory.java deleted file mode 100644 index 5341c5cef83c9aa3732224962e8203bb7fac9c2d..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/FilterSamplerFactory.java +++ /dev/null @@ -1,478 +0,0 @@ -/* - * 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.nodes.casts; - -import static com.oracle.truffle.r.nodes.casts.CastUtils.samples; - -import java.util.Arrays; -import java.util.Set; -import java.util.function.Predicate; - -import com.oracle.truffle.r.nodes.builtin.ArgumentFilter; -import com.oracle.truffle.r.nodes.builtin.casts.Filter; -import com.oracle.truffle.r.nodes.builtin.casts.Filter.AndFilter; -import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter; -import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.Dim; -import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.ElementAt; -import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.NATest; -import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.ScalarValue; -import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.StringLength; -import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.VectorSize; -import com.oracle.truffle.r.nodes.builtin.casts.Filter.DoubleFilter; -import com.oracle.truffle.r.nodes.builtin.casts.Filter.FilterVisitor; -import com.oracle.truffle.r.nodes.builtin.casts.Filter.MatrixFilter; -import com.oracle.truffle.r.nodes.builtin.casts.Filter.MissingFilter; -import com.oracle.truffle.r.nodes.builtin.casts.Filter.NotFilter; -import com.oracle.truffle.r.nodes.builtin.casts.Filter.NullFilter; -import com.oracle.truffle.r.nodes.builtin.casts.Filter.OrFilter; -import com.oracle.truffle.r.nodes.builtin.casts.Filter.RTypeFilter; -import com.oracle.truffle.r.nodes.builtin.casts.Filter.TypeFilter; -import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode.ArgumentFilterFactory; -import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -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.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; - -public final class FilterSamplerFactory - implements ArgumentFilterFactory, FilterVisitor<ArgumentFilterSampler<?, ?>>, MatrixFilter.OperationVisitor<ArgumentFilterSampler<RAbstractVector, RAbstractVector>>, - DoubleFilter.OperationVisitor<ArgumentFilterSampler<Double, Double>>, CompareFilter.SubjectVisitor<ArgumentFilterSampler<?, ?>> { - - public static final FilterSamplerFactory INSTANCE = new FilterSamplerFactory(); - - private FilterSamplerFactory() { - // singleton - } - - @Override - public ArgumentFilter<?, ?> createFilter(Filter<?, ?> filter) { - return filter.accept(this); - } - - private static <T, R> Predicate<T> toPredicate(ArgumentFilter<T, R> filter) { - return x -> filter.test(x); - } - - @SuppressWarnings("rawtypes") - @Override - public ArgumentFilterSampler<?, ?> visit(TypeFilter<?, ?> filter) { - Class<?>[] filterTypes = new Class[]{filter.getType1(), filter.getType2()}; - return TypePredicateArgumentFilterSampler.fromLambda(toPredicate(filter.getInstanceOfLambda()), - CastUtils.sampleValuesForClases(filterTypes), CastUtils.samples(null), filterTypes); - } - - @Override - public ArgumentFilterSampler<?, ?> visit(RTypeFilter<?> filter) { - if (filter.getType() == RType.Integer) { - return visit(new TypeFilter<>(Integer.class, RAbstractIntVector.class)); - } else if (filter.getType() == RType.Double) { - return visit(new TypeFilter<>(Double.class, RAbstractDoubleVector.class)); - } else if (filter.getType() == RType.Logical) { - return visit(new TypeFilter<>(Byte.class, RAbstractLogicalVector.class)); - } else if (filter.getType() == RType.Complex) { - return visit(new TypeFilter<>(RAbstractComplexVector.class)); - } else if (filter.getType() == RType.Character) { - return visit(new TypeFilter<>(String.class, RAbstractStringVector.class)); - } else if (filter.getType() == RType.Raw) { - return visit(new TypeFilter<>(RAbstractRawVector.class)); - } else { - throw RInternalError.unimplemented("TODO: more types here"); - } - } - - @Override - public ArgumentFilterSampler<?, ?> visit(CompareFilter<?> filter) { - return filter.getSubject().accept(this, filter.getOperation()); - } - - @SuppressWarnings("rawtypes") - @Override - public ArgumentFilterSampler<?, ?> visit(AndFilter<?, ?> filter) { - ArgumentFilterSampler leftFilter = filter.getLeft().accept(this); - ArgumentFilterSampler rightFilter = filter.getRight().accept(this); - return new ArgumentFilterSampler<Object, Object>() { - - @SuppressWarnings("unchecked") - @Override - public boolean test(Object arg) { - if (!leftFilter.test(arg)) { - return false; - } else { - return rightFilter.test(arg); - } - } - - @Override - public TypeExpr falseBranchType() { - return filter.isNarrowing() ? trueBranchType().not() : trueBranchType(); - } - - @Override - public TypeExpr trueBranchType() { - return leftFilter.trueBranchType().and(rightFilter.trueBranchType()); - } - - @SuppressWarnings({"unchecked"}) - @Override - public Samples<Object> collectSamples(TypeExpr inputType) { - Samples thisSamples = rightFilter.collectSamples(inputType); - Samples otherSamples = leftFilter.collectSamples(inputType); - - return thisSamples.and(otherSamples); - } - }; - } - - @SuppressWarnings("rawtypes") - @Override - public ArgumentFilterSampler<?, ?> visit(OrFilter<?> filter) { - ArgumentFilterSampler leftFilter = filter.getLeft().accept(this); - ArgumentFilterSampler rightFilter = filter.getRight().accept(this); - return new ArgumentFilterSampler<Object, Object>() { - - @SuppressWarnings("unchecked") - @Override - public boolean test(Object arg) { - if (leftFilter.test(arg)) { - return true; - } else { - return rightFilter.test(arg); - } - } - - @Override - public TypeExpr falseBranchType() { - return trueBranchType(); - } - - @Override - public TypeExpr trueBranchType() { - return leftFilter.trueBranchType().or(rightFilter.trueBranchType()); - } - - @SuppressWarnings("unchecked") - @Override - public Samples<Object> collectSamples(TypeExpr inputType) { - Samples thisSamples = leftFilter.collectSamples(inputType); - Samples otherSamples = rightFilter.collectSamples(inputType); - return Samples.<Object> anything().and(thisSamples).or(otherSamples); - } - }; - } - - @SuppressWarnings("rawtypes") - @Override - public ArgumentFilterSampler<?, ?> visit(NotFilter<?> filter) { - ArgumentFilterSampler toNegate = filter.getFilter().accept(this); - return new ArgumentFilterSampler<Object, Object>() { - - @SuppressWarnings("unchecked") - @Override - public boolean test(Object arg) { - return !toNegate.test(arg); - } - - @Override - public TypeExpr falseBranchType() { - return filter.getFilter().isNarrowing() ? trueBranchType() : trueBranchType(); - } - - @Override - public TypeExpr trueBranchType() { - return filter.getFilter().isNarrowing() ? toNegate.trueBranchType().not() : toNegate.trueBranchType(); - } - - @SuppressWarnings({"unchecked"}) - @Override - public Samples<Object> collectSamples(TypeExpr inputType) { - Samples thisSamples = toNegate.collectSamples(inputType); - return thisSamples.swap(); - } - }; - } - - @Override - public ArgumentFilterSampler<?, ?> visit(NullFilter filter) { - return new VectorPredicateArgumentFilterSampler<>("nullValue", x -> false); - } - - @Override - public ArgumentFilterSampler<?, ?> visit(MissingFilter filter) { - return new VectorPredicateArgumentFilterSampler<>("missingValue", x -> false); - } - - @Override - public ArgumentFilterSampler<?, ?> visit(MatrixFilter<?> filter) { - return filter.acceptOperation(this); - } - - @Override - public ArgumentFilterSampler<?, ?> visit(DoubleFilter filter) { - return filter.acceptOperation(this); - } - - @Override - public ArgumentFilterSampler<RAbstractVector, RAbstractVector> visitIsMatrix() { - return new VectorPredicateArgumentFilterSampler<>("matrix", x -> x.isMatrix()); - } - - @Override - public ArgumentFilterSampler<RAbstractVector, RAbstractVector> visitIsSquareMatrix() { - return new VectorPredicateArgumentFilterSampler<>("squareMatrix", x -> x.isMatrix() && x.getDimensions()[0] == x.getDimensions()[1], 3); - } - - @Override - public ArgumentFilterSampler<Double, Double> visitIsFinite() { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double x) -> !Double.isInfinite(x), samples(0d), samples(RRuntime.DOUBLE_NA), Double.class); - } - - @Override - public ArgumentFilterSampler<Double, Double> visitIsFractional() { - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double x) -> !RRuntime.isNAorNaN(x) && !Double.isInfinite(x) && x != Math.floor(x), samples(0d), samples(RRuntime.DOUBLE_NA), - Double.class); - } - - @Override - public ArgumentFilterSampler<?, ?> visit(ScalarValue scalarValue, byte operation) { - switch (operation) { - case CompareFilter.EQ: - switch (scalarValue.type) { - case Character: - final String s = (String) scalarValue.value; - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((String arg) -> arg.equals(s), samples(s), CastUtils.samples(null), String.class); - case Integer: - final int i = (int) scalarValue.value; - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Integer arg) -> arg == i, samples(i), CastUtils.<Integer> samples(i + 1), Integer.class); - case Double: - final double d = (double) scalarValue.value; - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double arg) -> arg == d, samples(d), CastUtils.<Double> samples(d + 1), Double.class); - case Logical: - final byte l = (byte) scalarValue.value; - Set<Byte> negativeSamples = null; - switch (l) { - case RRuntime.LOGICAL_TRUE: - negativeSamples = CastUtils.samples(RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA); - break; - case RRuntime.LOGICAL_FALSE: - negativeSamples = CastUtils.samples(RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_NA); - break; - case RRuntime.LOGICAL_NA: - negativeSamples = CastUtils.samples(RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE); - break; - } - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Byte arg) -> arg == l, samples(l), negativeSamples, Byte.class); - case Any: - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples(arg -> arg.equals(scalarValue.value), samples(), CastUtils.samples(null), scalarValue.value.getClass()); - default: - throw RInternalError.unimplemented("TODO: more types here "); - } - case CompareFilter.GT: - switch (scalarValue.type) { - case Integer: - final int i = (int) scalarValue.value; - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Integer arg) -> arg > i, samples(i + 1), samples(i), Integer.class); - case Double: - final double d = (double) scalarValue.value; - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double arg) -> arg > d, CastUtils.<Double> samples(), samples(d), Double.class); - default: - throw RInternalError.unimplemented("TODO: more types here"); - } - case CompareFilter.LT: - switch (scalarValue.type) { - case Integer: - final int i = (int) scalarValue.value; - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Integer arg) -> arg < i, samples(i - 1), samples(i), Integer.class); - case Double: - final double d = (double) scalarValue.value; - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double arg) -> arg < d, CastUtils.<Double> samples(), samples(d), Double.class); - default: - throw RInternalError.unimplemented("TODO: more types here"); - } - case CompareFilter.GE: - switch (scalarValue.type) { - case Integer: - final int i = (int) scalarValue.value; - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Integer arg) -> arg >= i, samples(i), samples(i - 1), Integer.class); - case Double: - final double d = (double) scalarValue.value; - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double arg) -> arg >= d, samples(d), samples(d - 1), Double.class); - default: - throw RInternalError.unimplemented("TODO: more types here"); - } - case CompareFilter.LE: - switch (scalarValue.type) { - case Integer: - final int i = (int) scalarValue.value; - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Integer arg) -> arg <= i, samples(i), samples(i + 1), Integer.class); - case Double: - final double d = (double) scalarValue.value; - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double arg) -> arg <= d, samples(d), samples(d + 1), Double.class); - default: - throw RInternalError.unimplemented("TODO: more types here"); - } - case CompareFilter.SAME: - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples(arg -> arg == scalarValue.value, samples(scalarValue.value), CastUtils.samples(null), scalarValue.value.getClass()); - - default: - throw RInternalError.unimplemented("TODO: more operations here"); - } - } - - @Override - public ArgumentFilterSampler<?, ?> visit(NATest naTest, byte operation) { - switch (operation) { - case CompareFilter.EQ: - switch (naTest.type) { - case Integer: - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Integer x) -> RRuntime.isNA(x), samples(RRuntime.INT_NA), samples(0), Integer.class); - case Double: - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double x) -> RRuntime.isNAorNaN(x), samples(RRuntime.DOUBLE_NA), samples(0d), Double.class); - case Logical: - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Byte x) -> RRuntime.isNA(x), samples(RRuntime.LOGICAL_NA), - samples(RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE), Byte.class); - case Character: - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((String x) -> RRuntime.isNA(x), samples(RRuntime.STRING_NA), samples(""), String.class); - case Complex: - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((RComplex x) -> x.isNA(), samples(RDataFactory.createComplex(RRuntime.COMPLEX_NA_REAL_PART, 0)), - samples(RDataFactory.createComplex(0, 0)), RComplex.class); - default: - throw RInternalError.unimplemented("TODO: more types here"); - } - default: - throw RInternalError.unimplemented("TODO: more operations here"); - } - } - - @Override - public ArgumentFilterSampler<String, String> visit(StringLength stringLength, byte operation) { - final int l = stringLength.length; - switch (operation) { - case CompareFilter.EQ: - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((String arg) -> arg.length() == l, samples(sampleString(l)), - samples(sampleString(l + 1)), String.class); - - case CompareFilter.GT: - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((String arg) -> arg.length() > l, samples(sampleString(l + 1)), - samples(sampleString(l)), String.class); - - case CompareFilter.LT: - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((String arg) -> arg.length() < l, samples(sampleString(l - 1)), - samples(sampleString(l)), String.class); - - case CompareFilter.GE: - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((String arg) -> arg.length() >= l, samples(sampleString(l)), - samples(sampleString(l - 1)), String.class); - - case CompareFilter.LE: - return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((String arg) -> arg.length() <= l, samples(sampleString(l)), - samples(sampleString(l + 1)), String.class); - - default: - throw RInternalError.unimplemented("TODO: more operations here"); - } - } - - private static String sampleString(int len) { - if (len < 0) { - return null; - } else if (len == 0) { - return ""; - } else { - char[] ch = new char[len]; - Arrays.fill(ch, 'a'); - return String.valueOf(ch); - } - } - - @Override - public ArgumentFilterSampler<RAbstractVector, RAbstractVector> visit(VectorSize vectorSize, byte operation) { - final int s = vectorSize.size; - switch (operation) { - case CompareFilter.EQ: - if (s == 0) { - return new VectorPredicateArgumentFilterSampler<>("size(int)", x -> x.getLength() == s, s - 1, s + 1); - } else { - return new VectorPredicateArgumentFilterSampler<>("size(int)", x -> x.getLength() == s, 0, s - 1, s + 1); - } - case CompareFilter.GT: - return new VectorPredicateArgumentFilterSampler<>("sizeGt(int)", x -> x.getLength() > s, s - 1, s); - - case CompareFilter.LT: - return new VectorPredicateArgumentFilterSampler<>("sizeLt(int)", x -> x.getLength() < s, s, s + 1); - - case CompareFilter.GE: - return new VectorPredicateArgumentFilterSampler<>("sizeGe(int)", x -> x.getLength() >= s, s - 1); - - case CompareFilter.LE: - return new VectorPredicateArgumentFilterSampler<>("sizeLe(int)", x -> x.getLength() <= s, s + 1); - - default: - throw RInternalError.unimplemented("TODO: more operations here"); - } - } - - @Override - public ArgumentFilterSampler<RAbstractVector, RAbstractVector> visit(ElementAt elementAt, byte operation) { - final int index = elementAt.index; - switch (operation) { - case CompareFilter.EQ: - switch (elementAt.type) { - case Integer: - int i = (int) elementAt.value; - return new VectorPredicateArgumentFilterSampler<>("elementAt", x -> index < x.getLength() && i == (int) (x.getDataAtAsObject(index)), 0, index); - case Double: - double d = (double) elementAt.value; - return new VectorPredicateArgumentFilterSampler<>("elementAt", x -> index < x.getLength() && d == (double) (x.getDataAtAsObject(index)), 0, index); - case Logical: - byte l = (byte) elementAt.value; - return new VectorPredicateArgumentFilterSampler<>("elementAt", x -> index < x.getLength() && l == (byte) (x.getDataAtAsObject(index)), 0, index); - case Character: - case Complex: - return new VectorPredicateArgumentFilterSampler<>("elementAt", x -> index < x.getLength() && elementAt.value.equals(x.getDataAtAsObject(index)), 0, index); - default: - throw RInternalError.unimplemented("TODO: more types here"); - } - default: - throw RInternalError.unimplemented("TODO: more operations here"); - } - } - - @Override - public ArgumentFilterSampler<RAbstractVector, RAbstractVector> visit(Dim dim, byte operation) { - switch (operation) { - case CompareFilter.EQ: - return new VectorPredicateArgumentFilterSampler<>("dimEq", v -> v.isMatrix() && v.getDimensions().length > dim.dimIndex && v.getDimensions()[dim.dimIndex] == dim.dimSize, 3); - case CompareFilter.GT: - return new VectorPredicateArgumentFilterSampler<>("dimGt", v -> v.isMatrix() && v.getDimensions().length > dim.dimIndex && v.getDimensions()[dim.dimIndex] > dim.dimSize, 3); - default: - throw RInternalError.unimplemented("TODO: more operations here"); - } - } -} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MapperSamplerFactory.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MapperSamplerFactory.java deleted file mode 100644 index 078025424b81a925c04df8a7daa619afc9312be9..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MapperSamplerFactory.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2016, 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.casts; - -import static com.oracle.truffle.r.nodes.casts.CastUtils.samples; - -import com.oracle.truffle.r.nodes.builtin.ArgumentMapper; -import com.oracle.truffle.r.nodes.builtin.casts.Mapper; -import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapByteToBoolean; -import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapDoubleToInt; -import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapToCharAt; -import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapToValue; -import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapperVisitor; -import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode.ArgumentMapperFactory; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.ops.na.NACheck; - -public final class MapperSamplerFactory implements ArgumentMapperFactory, MapperVisitor<ValuePredicateArgumentMapperSampler<?, ?>> { - - public static final MapperSamplerFactory INSTANCE = new MapperSamplerFactory(); - - private MapperSamplerFactory() { - // singleton - } - - @Override - public ArgumentMapper<?, ?> createMapper(Mapper<?, ?> mapper) { - return mapper.accept(this); - } - - @Override - public ValuePredicateArgumentMapperSampler<Object, Object> visit(MapToValue<?, ?> mapper) { - final Object value = mapper.getValue(); - return ValuePredicateArgumentMapperSampler.fromLambda(x -> value, x -> null, CastUtils.samples(), CastUtils.samples(), null, value.getClass()); - } - - @Override - public ValuePredicateArgumentMapperSampler<?, ?> visit(MapByteToBoolean mapper) { - return ValuePredicateArgumentMapperSampler.fromLambda(x -> RRuntime.fromLogical(x), (Boolean x) -> RRuntime.asLogical(x), - samples(RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA), - CastUtils.<Byte> samples(), Byte.class, Boolean.class); - } - - @Override - public ValuePredicateArgumentMapperSampler<?, ?> visit(MapDoubleToInt mapper) { - final NACheck naCheck = NACheck.create(); - return ValuePredicateArgumentMapperSampler.fromLambda(x -> { - naCheck.enable(x); - return naCheck.convertDoubleToInt(x); - }, x -> x == null ? null : (double) x, Double.class, Integer.class); - } - - @Override - public ValuePredicateArgumentMapperSampler<?, ?> visit(MapToCharAt mapper) { - final int defaultValue = mapper.getDefaultValue(); - - return ValuePredicateArgumentMapperSampler.fromLambda(x -> { - if (x == null || x.isEmpty()) { - return defaultValue; - } else { - if (x == RRuntime.STRING_NA) { - return RRuntime.INT_NA; - } else { - return (int) x.charAt(0); - } - } - }, x -> { - if (x == null) { - return defaultValue == RRuntime.INT_NA ? RRuntime.STRING_NA : "" + (char) defaultValue; - } else { - return x.equals(RRuntime.INT_NA) ? RRuntime.STRING_NA : x.toString(); - } - }, samples(defaultValue == RRuntime.INT_NA ? RRuntime.STRING_NA : "" + (char) defaultValue), CastUtils.<String> samples(), String.class, Integer.class); - } -} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MarkLookup.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MarkLookup.java new file mode 100644 index 0000000000000000000000000000000000000000..f68d4c13316cf162a85e463ecc718943486562e5 --- /dev/null +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MarkLookup.java @@ -0,0 +1,238 @@ +/* + * 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.nodes.casts; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import com.oracle.truffle.r.nodes.builtin.casts.Filter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.AndFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.DoubleFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.FilterVisitor; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.MatrixFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.MissingFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.NotFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.NullFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.OrFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.RTypeFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.TypeFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Mapper; +import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapByteToBoolean; +import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapDoubleToInt; +import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapToCharAt; +import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapToValue; +import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapperVisitor; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.AttributableCoercionStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.BoxPrimitiveStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.NotNAStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.PipelineStepVisitor; + +public final class MarkLookup implements PipelineStepVisitor<Map<String, Object>>, FilterVisitor<Map<String, Object>>, MapperVisitor<Map<String, Object>> { + private final Map<Object, String> marx = new HashMap<>(); + + public static final MarkLookup INSTANCE = new MarkLookup(); + + private MarkLookup() { + } + + public static void clear() { + INSTANCE.marx.clear(); + } + + public static <T, S extends T, F extends Filter<T, S>> F mark(F filter, String m) { + INSTANCE.marx.put(filter, m); + return filter; + } + + public static <T, S, M extends Mapper<T, S>> M mark(M mapper, String m) { + INSTANCE.marx.put(mapper, m); + return mapper; + } + + public static Map<String, Object> lookup(PipelineStep<?, ?> firstStep, String... filterNames) { + return lookup(firstStep, Arrays.stream(filterNames).collect(Collectors.toSet())); + } + + public static Map<String, Object> lookup(PipelineStep<?, ?> firstStep, Set<String> filterNames) { + Map<String, Object> foundMarks = new HashMap<>(); + for (String key : filterNames) { + foundMarks.put(key, null); + } + return lookup(firstStep, foundMarks); + } + + public static Map<String, Object> lookup(PipelineStep<?, ?> firstStep, Map<String, Object> foundMarks) { + return firstStep.acceptPipeline(INSTANCE, foundMarks); + } + + @Override + public Map<String, Object> visit(FindFirstStep<?, ?> step, Map<String, Object> foundMarks) { + return foundMarks; + } + + @Override + public Map<String, Object> visit(CoercionStep<?, ?> step, Map<String, Object> foundMarks) { + return foundMarks; + } + + @Override + public Map<String, Object> visit(MapStep<?, ?> step, Map<String, Object> foundMarks) { + return step.getMapper().accept(this, foundMarks); + } + + @Override + public Map<String, Object> visit(MapIfStep<?, ?> step, Map<String, Object> foundMarks) { + Map<String, Object> found = foundMarks; + found = step.getFilter().accept(this, found); + if (step.getTrueBranch() != null) { + found = step.getTrueBranch().accept(this, found); + } + if (step.getFalseBranch() != null) { + found = step.getFalseBranch().accept(this, found); + } + return found; + } + + @Override + public Map<String, Object> visit(FilterStep<?, ?> step, Map<String, Object> foundMarks) { + return step.getFilter().accept(this, foundMarks); + } + + @Override + public Map<String, Object> visit(NotNAStep<?> step, Map<String, Object> foundMarks) { + return foundMarks; + } + + @Override + public Map<String, Object> visit(BoxPrimitiveStep<?> step, Map<String, Object> foundMarks) { + return foundMarks; + } + + @Override + public Map<String, Object> visit(AttributableCoercionStep<?> step, Map<String, Object> foundMarks) { + return foundMarks; + } + + // Filter visitor + + public Map<String, Object> visitFilter(Filter<?, ?> filter, Map<String, Object> foundMarks) { + String mark = marx.get(filter); + if (mark != null && foundMarks.containsKey(mark)) { + foundMarks.put(mark, filter); + } + return foundMarks; + } + + @Override + public Map<String, Object> visit(TypeFilter<?, ?> filter, Map<String, Object> foundMarks) { + return visitFilter(filter, foundMarks); + } + + @Override + public Map<String, Object> visit(RTypeFilter<?> filter, Map<String, Object> foundMarks) { + return visitFilter(filter, foundMarks); + } + + @Override + public Map<String, Object> visit(CompareFilter<?> filter, Map<String, Object> foundMarks) { + return visitFilter(filter, foundMarks); + } + + @Override + public Map<String, Object> visit(AndFilter<?, ?> filter, Map<String, Object> foundMarks) { + Map<String, Object> found = filter.getLeft().accept(this, visitFilter(filter, foundMarks)); + return filter.getRight().accept(this, filter.getLeft().accept(this, found)); + } + + @Override + public Map<String, Object> visit(OrFilter<?> filter, Map<String, Object> foundMarks) { + Map<String, Object> found = filter.getLeft().accept(this, visitFilter(filter, foundMarks)); + return filter.getRight().accept(this, filter.getLeft().accept(this, found)); + } + + @Override + public Map<String, Object> visit(NotFilter<?> filter, Map<String, Object> foundMarks) { + return filter.getFilter().accept(this, visitFilter(filter, foundMarks)); + } + + @Override + public Map<String, Object> visit(MatrixFilter<?> filter, Map<String, Object> foundMarks) { + return visitFilter(filter, foundMarks); + } + + @Override + public Map<String, Object> visit(DoubleFilter filter, Map<String, Object> foundMarks) { + return visitFilter(filter, foundMarks); + } + + @Override + public Map<String, Object> visit(NullFilter filter, Map<String, Object> foundMarks) { + return visitFilter(filter, foundMarks); + } + + @Override + public Map<String, Object> visit(MissingFilter filter, Map<String, Object> foundMarks) { + return visitFilter(filter, foundMarks); + } + + // Mapper visitor + + public Map<String, Object> visitMapper(Mapper<?, ?> mapper, Map<String, Object> foundMarks) { + String mark = marx.get(mapper); + if (mark != null && foundMarks.containsKey(mark)) { + foundMarks.put(mark, mapper); + } + return foundMarks; + } + + @Override + public Map<String, Object> visit(MapToValue<?, ?> mapper, Map<String, Object> foundMarks) { + return visitMapper(mapper, foundMarks); + } + + @Override + public Map<String, Object> visit(MapByteToBoolean mapper, Map<String, Object> foundMarks) { + return visitMapper(mapper, foundMarks); + } + + @Override + public Map<String, Object> visit(MapDoubleToInt mapper, Map<String, Object> foundMarks) { + return visitMapper(mapper, foundMarks); + } + + @Override + public Map<String, Object> visit(MapToCharAt mapper, Map<String, Object> foundMarks) { + return visitMapper(mapper, foundMarks); + } + +} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Not.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Not.java index 0583db597d22d79ed8015ae0fb7b3dfc8215da2d..28d9ff8fff17fa4111c989f2922807e5896b068c 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Not.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Not.java @@ -29,19 +29,33 @@ public final class Not<T> implements Type, TypeAndInstanceCheck { public static final Not<Object> NOTHING = new Not<>(Object.class); - private final Class<T> negated; + private final Type negated; - private Not(Class<T> negated) { + private Not(Type negated) { this.negated = negated; } - public Class<T> getNegated() { + public Type getNegated() { return this.negated; } @Override public boolean isInstance(Object x) { - return !negated.isInstance(x); + if (negated instanceof TypeAndInstanceCheck) { + return !((TypeAndInstanceCheck) negated).isInstance(x); + } else { + assert negated instanceof Class; + return !((Class<?>) negated).isInstance(x); + } + } + + @Override + public Type normalize() { + if (negated instanceof TypeAndInstanceCheck) { + return new Not<>(((TypeAndInstanceCheck) negated).normalize()); + } else { + return this; + } } public static boolean isNegative(Type t) { @@ -61,13 +75,13 @@ public final class Not<T> implements Type, TypeAndInstanceCheck { return getPositiveType(t); } else { assert t instanceof Class; - return new Not<>((Class<?>) t); + return new Not<>(t); } } @Override public String toString() { - return "Not(" + negated.getSimpleName() + ")"; + return "Not(" + (negated instanceof Class ? ((Class<?>) negated).getSimpleName() : negated.toString()) + ")"; } @Override @@ -90,7 +104,7 @@ public final class Not<T> implements Type, TypeAndInstanceCheck { return false; } Not<?> other = (Not<?>) obj; - return other.negated == this.negated; + return other.negated.equals(this.negated); } @Override diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java new file mode 100644 index 0000000000000000000000000000000000000000..782929e761a47fd0745e6ebbd48e365cb08c76cb --- /dev/null +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java @@ -0,0 +1,420 @@ +/* + * 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.nodes.casts; + +import static com.oracle.truffle.r.nodes.casts.TypeExpr.atom; + +import java.lang.reflect.Type; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import com.oracle.truffle.r.nodes.builtin.casts.ExecutionPathVisitor; +import com.oracle.truffle.r.nodes.builtin.casts.Filter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.AndFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.Dim; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.ElementAt; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.NATest; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.ScalarValue; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.StringLength; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.SubjectVisitor; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.VectorSize; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.DoubleFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.FilterVisitor; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.MatrixFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.MissingFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.NotFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.NullFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.OrFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.RTypeFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.TypeFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapByteToBoolean; +import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapDoubleToInt; +import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapToCharAt; +import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapToValue; +import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapperVisitor; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.AttributableCoercionStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.BoxPrimitiveStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.NotNAStep; +import com.oracle.truffle.r.nodes.unary.CastComplexNode; +import com.oracle.truffle.r.nodes.unary.CastDoubleBaseNode; +import com.oracle.truffle.r.nodes.unary.CastDoubleNode; +import com.oracle.truffle.r.nodes.unary.CastIntegerBaseNode; +import com.oracle.truffle.r.nodes.unary.CastIntegerNode; +import com.oracle.truffle.r.nodes.unary.CastLogicalBaseNode; +import com.oracle.truffle.r.nodes.unary.CastLogicalNode; +import com.oracle.truffle.r.nodes.unary.CastNode; +import com.oracle.truffle.r.nodes.unary.CastRawNode; +import com.oracle.truffle.r.nodes.unary.CastStringBaseNode; +import com.oracle.truffle.r.nodes.unary.CastStringNode; +import com.oracle.truffle.r.nodes.unary.CastToAttributableNode; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.Utils; +import com.oracle.truffle.r.runtime.data.RComplex; +import com.oracle.truffle.r.runtime.data.RDouble; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RInteger; +import com.oracle.truffle.r.runtime.data.RLogical; +import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RRaw; +import com.oracle.truffle.r.runtime.data.RString; +import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; +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.RAbstractLogicalVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +public class ResultTypesAnalyser extends ExecutionPathVisitor<TypeExpr> implements MapperVisitor<TypeExpr>, FilterVisitor<TypeExpr>, SubjectVisitor<TypeExpr> { + + private static final TypeExpr NOT_NULL_NOT_MISSING = atom(RNull.class).not().and(atom(RMissing.class).not()); + + public static TypeExpr analyse(PipelineStep<?, ?> firstStep) { + return analyse(firstStep, TypeExpr.ANYTHING); + } + + public static TypeExpr analyse(PipelineStep<?, ?> firstStep, TypeExpr inputType) { + List<TypeExpr> pathResults = new ResultTypesAnalyser().visitPaths(firstStep, inputType); + return pathResults.stream().reduce((x, y) -> x.or(y)).get(); + } + + @Override + public TypeExpr visit(FindFirstStep<?, ?> step, TypeExpr inputType) { + TypeExpr rt; + if (step.getElementClass() == null || step.getElementClass() == Object.class) { + if (inputType.isAnything()) { + rt = atom(RAbstractVector.class).not(); + } else { + Set<Type> resTypes = inputType.classify().stream().map(c -> CastUtils.elementType(c)).collect(Collectors.toSet()); + rt = TypeExpr.union(resTypes); + } + } else { + rt = atom(step.getElementClass()); + } + + // findFirstOrNull + if (step.getDefaultValue() == RNull.instance) { + rt = rt.or(atom(RNull.class)); + } + + if (step.getDefaultValue() != null) { + rt = rt.positiveSamples(step.getDefaultValue()); + } else { + rt = rt.and(atom(RNull.class).not()).and(atom(RMissing.class).not()); + } + + return rt; + } + + private static TypeExpr inferResultTypeFromSpecializations(Class<? extends CastNode> castNodeClass, TypeExpr inputType) { + return CastUtils.Casts.createCastNodeCasts(castNodeClass).narrow(inputType); + } + + @Override + public TypeExpr visit(CoercionStep<?, ?> step, TypeExpr inputType) { + RType type = step.getType(); + TypeExpr res; + switch (type) { + case Integer: + res = step.vectorCoercion ? inferResultTypeFromSpecializations(CastIntegerNode.class, inputType) : inferResultTypeFromSpecializations(CastIntegerBaseNode.class, inputType); + break; + case Double: + res = step.vectorCoercion ? inferResultTypeFromSpecializations(CastDoubleNode.class, inputType) : inferResultTypeFromSpecializations(CastDoubleBaseNode.class, inputType); + break; + case Character: + res = step.vectorCoercion ? inferResultTypeFromSpecializations(CastStringNode.class, inputType) : inferResultTypeFromSpecializations(CastStringBaseNode.class, inputType); + break; + case Logical: + res = step.vectorCoercion ? inferResultTypeFromSpecializations(CastLogicalNode.class, inputType) : inferResultTypeFromSpecializations(CastLogicalBaseNode.class, inputType); + break; + case Complex: + res = inferResultTypeFromSpecializations(CastComplexNode.class, inputType); + break; + case Raw: + res = inferResultTypeFromSpecializations(CastRawNode.class, inputType); + break; + case Any: + TypeExpr funOrVecTp = atom(RFunction.class).or(atom(RAbstractVector.class)); + res = inputType.and(funOrVecTp); + break; + default: + throw RInternalError.shouldNotReachHere(Utils.stringFormat("Unsupported type '%s' in AsVectorStep", type)); + } + + if (step.preserveNonVector) { + TypeExpr maskedNullMissing = inputType.and(atom(RNull.class).or(atom(RMissing.class))); + res = res.or(maskedNullMissing); + } + + return res; + } + + @Override + public TypeExpr visit(MapStep<?, ?> step, TypeExpr inputType) { + return step.getMapper().accept(this, inputType); + } + + @Override + protected TypeExpr visitBranch(MapIfStep<?, ?> step, TypeExpr inputType, boolean visitTrueBranch) { + TypeExpr filterRes = visitFilter(step.getFilter(), inputType); + if (visitTrueBranch) { + if (step.isReturns()) { + TypeExpr returnedType = trueBranchResultTypes(step, inputType, filterRes); + return returnedType; + } else { + return trueBranchResultTypes(step, inputType, filterRes); + } + } else { + return falseBranchResultTypes(step, inputType, filterRes); + } + } + + private static TypeExpr trueBranchResultTypes(MapIfStep<?, ?> step, TypeExpr inputType, TypeExpr filterRes) { + TypeExpr filterTrueCaseType = inputType.and(filterRes); + if (step.getTrueBranch() != null) { + return analyse(step.getTrueBranch(), filterTrueCaseType); + } else { + return filterTrueCaseType; + } + } + + private static TypeExpr falseBranchResultTypes(MapIfStep<?, ?> step, TypeExpr inputType, TypeExpr filterRes) { + TypeExpr filterFalseCaseType = inputType.and(filterRes.not()); + if (step.getFalseBranch() != null) { + return analyse(step.getFalseBranch(), filterFalseCaseType); + } else { + return filterFalseCaseType; + } + } + + @Override + public TypeExpr visit(FilterStep<?, ?> step, TypeExpr inputType) { + if (step.isWarning()) { + return inputType; + } else { + return inputType.and(visitFilter(step.getFilter(), inputType)); + } + } + + @Override + public TypeExpr visit(NotNAStep<?> step, TypeExpr inputType) { + Set<Object> naSamples = inputType.toNormalizedConjunctionSet().stream().filter(t -> t instanceof Class).map(t -> CastUtils.naValue((Class<?>) t)).filter(x -> x != null).collect( + Collectors.toSet()); + TypeExpr resType = inputType.lower(step); + resType = resType.negativeSamples(naSamples); + if (step.getReplacement() != null) { + resType = resType.positiveSamples(step.getReplacement()); + } + return resType; + } + + @Override + public TypeExpr visit(BoxPrimitiveStep<?> step, TypeExpr inputType) { + TypeExpr noPrimType = atom(Integer.class).not().and(atom(Byte.class).not()).and(atom(Double.class).not()).and(atom(String.class).not()); + // cancel potential primitive types in the input + TypeExpr noPrimInput = inputType.and(noPrimType); + // the positive output type union + TypeExpr res = TypeExpr.union(RInteger.class, RLogical.class, RDouble.class, RString.class); + // intersect the to stop propagating the primitive types, such as String + res = res.and(noPrimInput); + // the output of the boxing is actually the union of the positive union with its negation + // that represents the fallback output for non-vectors + TypeExpr negRes = res.not().and(noPrimInput); + res = res.or(negRes); + return res; + } + + @Override + public TypeExpr visit(AttributableCoercionStep<?> step, TypeExpr inputType) { + return inferResultTypeFromSpecializations(CastToAttributableNode.class, inputType); + } + + // MapperVisitor + + @Override + public TypeExpr visit(MapToValue<?, ?> mapper, TypeExpr inputType) { + return atom(mapper.getValue().getClass()).lower(mapper); + } + + @Override + public TypeExpr visit(MapByteToBoolean mapper, TypeExpr inputType) { + return atom(Boolean.class); + } + + @Override + public TypeExpr visit(MapDoubleToInt mapper, TypeExpr inputType) { + return atom(Integer.class); + } + + @Override + public TypeExpr visit(MapToCharAt mapper, TypeExpr inputType) { + return atom(Integer.class); + } + + // FilterVisitor + + private TypeExpr visitFilter(Filter<?, ?> filter, TypeExpr inputType) { + return filter.accept(this, inputType); + } + + @Override + public TypeExpr visit(TypeFilter<?, ?> filter, TypeExpr inputType) { + TypeExpr resTp = atom(filter.getType1()); + if (filter.getType2() != null) { + resTp = resTp.or(atom(filter.getType2())); + } + return resTp.and(NOT_NULL_NOT_MISSING); + } + + @Override + public TypeExpr visit(RTypeFilter<?> filter, TypeExpr previous) { + switch (filter.getType()) { + case Integer: + return visit(new TypeFilter<>(Integer.class, RAbstractIntVector.class), previous); + case Double: + return visit(new TypeFilter<>(Double.class, RAbstractDoubleVector.class), previous); + case Logical: + return visit(new TypeFilter<>(Byte.class, RAbstractLogicalVector.class), previous); + case Complex: + return visit(new TypeFilter<>(RAbstractComplexVector.class), previous); + case Character: + return visit(new TypeFilter<>(String.class, RAbstractStringVector.class), previous); + case Raw: + return visit(new TypeFilter<>(RAbstractRawVector.class), previous); + default: + throw RInternalError.unimplemented("TODO: more types here"); + } + } + + @Override + public TypeExpr visit(CompareFilter<?> filter, TypeExpr previous) { + return filter.getSubject().accept(this, filter.getOperation(), previous).lower(filter); + } + + @Override + public TypeExpr visit(AndFilter<?, ?> filter, TypeExpr previous) { + TypeExpr res1 = visitFilter(filter.getLeft(), previous); + TypeExpr res2 = visitFilter(filter.getRight(), res1); + TypeExpr res = res1.and(res2); + return res; + } + + @Override + public TypeExpr visit(OrFilter<?> filter, TypeExpr previous) { + TypeExpr res1 = visitFilter(filter.getLeft(), previous); + TypeExpr res2 = visitFilter(filter.getRight(), previous); + TypeExpr res = res1.or(res2); + return res; + } + + @Override + public TypeExpr visit(NotFilter<?> filter, TypeExpr previous) { + return visitFilter(filter.getFilter(), previous).not(); + } + + @Override + public TypeExpr visit(MatrixFilter<?> filter, TypeExpr previous) { + return previous.lower(filter).and(NOT_NULL_NOT_MISSING); + } + + @Override + public TypeExpr visit(DoubleFilter filter, TypeExpr previous) { + return previous.lower(filter); + } + + @Override + public TypeExpr visit(NullFilter filter, TypeExpr previous) { + TypeExpr res = atom(RNull.class); + return res; + } + + @Override + public TypeExpr visit(MissingFilter filter, TypeExpr previous) { + TypeExpr res = atom(RMissing.class); + return res; + } + + // CompareFilter.SubjectVisitor + + @Override + public TypeExpr visit(ScalarValue scalarValue, byte operation, TypeExpr previous) { + return visitRType(scalarValue.type); + } + + private static TypeExpr visitRType(RType type) { + switch (type) { + case Integer: + return atom(Integer.class); + case Double: + return atom(Double.class); + case Logical: + return atom(Byte.class); + case Complex: + return atom(RComplex.class); + case Character: + return atom(String.class); + case Raw: + return atom(RRaw.class); + case Any: + return TypeExpr.ANYTHING; + default: + throw RInternalError.unimplemented("Unexpected type: " + type); + } + } + + @Override + public TypeExpr visit(NATest naTest, byte operation, TypeExpr previous) { + return visitRType(naTest.type); + } + + @Override + public TypeExpr visit(StringLength stringLength, byte operation, TypeExpr previous) { + return previous; + } + + @Override + public TypeExpr visit(VectorSize vectorSize, byte operation, TypeExpr previous) { + return previous.and(NOT_NULL_NOT_MISSING); + } + + @Override + public TypeExpr visit(ElementAt elementAt, byte operation, TypeExpr previous) { + return previous.and(NOT_NULL_NOT_MISSING); + } + + @Override + public TypeExpr visit(Dim dim, byte operation, TypeExpr previous) { + return previous.and(NOT_NULL_NOT_MISSING); + } + +} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Samples.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Samples.java index 3a65ebcc6d0c5373efe94d1f363de221d95fe278..63a2205440477836865b0c2c8a3837f11b1220c9 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Samples.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Samples.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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.casts; +import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Optional; @@ -49,13 +50,13 @@ public final class Samples<T> { return (Samples<T>) NOTHING; } - private final Set<? extends T> posSamples; - private final Set<?> negSamples; + private final Set<Object> posSamples; + private final Set<Object> negSamples; private final Predicate<Object> posMembership; private final Predicate<Object> negMembership; private final String name; - public Samples(String name, Set<? extends T> positiveSamples, Set<?> negativeSamples, Predicate<Object> posMembership) { + public Samples(String name, Set<Object> positiveSamples, Set<Object> negativeSamples, Predicate<Object> posMembership) { this.name = name; this.posSamples = positiveSamples; this.negSamples = negativeSamples; @@ -63,7 +64,7 @@ public final class Samples<T> { this.negMembership = CastUtils.instrument(this.posMembership.negate(), "neg(" + name + ")"); } - private Samples(String name, Set<? extends T> positiveSamples, Set<?> negativeSamples, Predicate<Object> posMembership, Predicate<Object> negMembership) { + private Samples(String name, Set<Object> positiveSamples, Set<Object> negativeSamples, Predicate<Object> posMembership, Predicate<Object> negMembership) { this.name = name; this.posSamples = positiveSamples; this.negSamples = negativeSamples; @@ -71,11 +72,23 @@ public final class Samples<T> { this.negMembership = CastUtils.instrument(negMembership, "neg(" + name + ")"); } - public Set<? extends T> positiveSamples() { + public Samples<T> addPositiveSamples(Object... sampleValues) { + Set<Object> newPosSamples = new HashSet<>(Arrays.asList(sampleValues)); + newPosSamples.addAll(posSamples); + return new Samples<>(name, newPosSamples, negSamples, posMembership, negMembership); + } + + public Samples<T> addNegativeSamples(Object... sampleValues) { + Set<Object> newNegSamples = new HashSet<>(Arrays.asList(sampleValues)); + newNegSamples.addAll(negSamples); + return new Samples<>(name, posSamples, newNegSamples, posMembership, negMembership); + } + + public Set<Object> positiveSamples() { return posSamples; } - public Set<?> negativeSamples() { + public Set<Object> negativeSamples() { return negSamples; } @@ -85,11 +98,11 @@ public final class Samples<T> { return all; } - public <R> Samples<R> map(Function<T, R> posMapper, Function<Object, Object> negMapper, Function<Object, Optional<T>> posUnmapper, Function<Object, Optional<Object>> negUnmapper) { - Set<R> mappedPositive = positiveSamples().stream().map(posMapper).collect(Collectors.toSet()); + public <R> Samples<R> map(Function<Object, R> posMapper, Function<Object, Object> negMapper, Function<Object, Optional<Object>> posUnmapper, Function<Object, Optional<Object>> negUnmapper) { + Set<Object> mappedPositive = positiveSamples().stream().map(posMapper).collect(Collectors.toSet()); Set<Object> mappedNegative = negativeSamples().stream().map(negMapper).collect(Collectors.toSet()); return new Samples<>(name + ".map", mappedPositive, mappedNegative, x -> { - Optional<T> um = posUnmapper.apply(x); + Optional<Object> um = posUnmapper.apply(x); return um.isPresent() ? posMembership.test(um.get()) : false; }, x -> { Optional<Object> um = negUnmapper.apply(x); @@ -102,14 +115,13 @@ public final class Samples<T> { } public Samples<T> filter(Predicate<Object> newPosCondition, Predicate<Object> newNegCondition) { - Set<T> newPositive = positiveSamples().stream().filter(newPosCondition).collect(Collectors.toSet()); + Set<Object> newPositive = positiveSamples().stream().filter(newPosCondition).collect(Collectors.toSet()); Set<Object> newNegative = negativeSamples().stream().filter(newNegCondition).collect(Collectors.toSet()); return new Samples<>(name + ".filter", newPositive, newNegative, x -> posMembership.test(x) && newPosCondition.test(x), x -> negMembership.test(x) && newNegCondition.test(x)); } - @SuppressWarnings("unchecked") - public Samples<T> and(Samples<? extends T> other) { + public Samples<T> and(Samples<?> other) { String newName = "and(" + name + "," + other.name + ")"; Set<Object> negativeUnion = new HashSet<>(other.negativeSamples()); @@ -126,10 +138,9 @@ public final class Samples<T> { Predicate<Object> newPosCondition = CastUtils.instrument(posMembership.and(other.posMembership), "and-pos"); positiveUnion.removeIf(CastUtils.instrument(newPosCondition.negate(), "pruningPosUnion:" + newName)); - return new Samples<>(newName, (Set<T>) positiveUnion, negativeUnion, newPosCondition, newNegCondition); + return new Samples<>(newName, positiveUnion, negativeUnion, newPosCondition, newNegCondition); } - @SuppressWarnings("unchecked") public Samples<T> or(Samples<?> other) { String newName = "or(" + name + "," + other.name + ")"; @@ -147,7 +158,7 @@ public final class Samples<T> { Predicate<Object> newPosCondition = CastUtils.instrument(posMembership.or(other.posMembership), "or-neg"); positiveUnion.removeIf(CastUtils.instrument(newPosCondition.negate(), "pruningPosUnion:" + newName)); - return new Samples<>(newName, (Set<T>) positiveUnion, negativeUnion, newPosCondition, newNegCondition); + return new Samples<>(newName, positiveUnion, negativeUnion, newPosCondition, newNegCondition); } public Samples<Object> swap() { diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/SamplesCollector.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/SamplesCollector.java new file mode 100644 index 0000000000000000000000000000000000000000..e4a2b528cbb42b3328d75dfffc8351583a5d2a0f --- /dev/null +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/SamplesCollector.java @@ -0,0 +1,462 @@ +/* + * 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.nodes.casts; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; + +import com.oracle.truffle.r.nodes.builtin.casts.ExecutionPathVisitor; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.AndFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.Dim; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.ElementAt; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.NATest; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.ScalarValue; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.StringLength; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.VectorSize; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.DoubleFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.FilterVisitor; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.MatrixFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.MissingFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.NotFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.NullFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.OrFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.RTypeFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Filter.TypeFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapByteToBoolean; +import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapDoubleToInt; +import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapToCharAt; +import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapToValue; +import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapperVisitor; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.AttributableCoercionStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.BoxPrimitiveStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.NotNAStep; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +public class SamplesCollector extends ExecutionPathVisitor<Consumer<Object>> + implements FilterVisitor<Consumer<Object>>, CompareFilter.SubjectVisitor<Consumer<Object>>, MapperVisitor<Consumer<Object>> { + + public static Set<Object> collect(PipelineStep<?, ?> firstStep) { + Set<Object> samples = new HashSet<>(); + collect(firstStep, s -> samples.add(s)); + return samples; + } + + public static Consumer<Object> collect(PipelineStep<?, ?> firstStep, Consumer<Object> initial) { + List<Consumer<Object>> pathResults = new SamplesCollector().visitPaths(firstStep, initial); + return pathResults.stream().reduce((x, y) -> s -> { + x.accept(s); + y.accept(s); + }).get(); + } + + @Override + public Consumer<Object> visit(FindFirstStep<?, ?> step, Consumer<Object> previous) { + if (step.getDefaultValue() != null) { + previous.accept(step.getDefaultValue()); + previous.accept(RNull.instance); + previous.accept(RMissing.instance); + } + return s -> { + previous.accept(s); + }; + } + + @Override + public Consumer<Object> visit(CoercionStep<?, ?> step, Consumer<Object> previous) { + Set<?> samples = CastUtils.sampleValuesForClasses(CastUtils.rTypeToClasses(step.getType())); + for (Object s : samples) { + previous.accept(s); + } + + previous.accept(RNull.instance); + previous.accept(RMissing.instance); + + return s -> { + if (s instanceof VectorPlaceholder) { + previous.accept(CastUtils.vectorOfSize(step.type, ((VectorPlaceholder) s).size)); + } else { + previous.accept(s); + } + }; + } + + @Override + public Consumer<Object> visit(MapStep<?, ?> step, Consumer<Object> previous) { + previous.accept(RNull.instance); + previous.accept(RMissing.instance); + + return step.getMapper().accept(this, previous); + } + + @Override + protected Consumer<Object> visitBranch(MapIfStep<?, ?> step, Consumer<Object> previous, boolean visitTrueBranch) { + + Consumer<Object> filterConsumer = step.getFilter().accept(this, s -> previous.accept(s)); + + PipelineStep<?, ?> branch; + if (visitTrueBranch) { + branch = step.getTrueBranch(); + } else { + branch = step.getFalseBranch(); + } + Consumer<Object> branchSampler = branch != null ? collect(branch, s -> { + filterConsumer.accept(s); + }) : s -> filterConsumer.accept(s); + return s -> { + branchSampler.accept(s); + }; + } + + @Override + public Consumer<Object> visit(FilterStep<?, ?> step, Consumer<Object> previous) { + previous.accept(RNull.instance); + previous.accept(RMissing.instance); + + Consumer<Object> filterConsumer = step.getFilter().accept(this, s -> previous.accept(s)); + + return s -> { + filterConsumer.accept(s); + }; + } + + @Override + public Consumer<Object> visit(NotNAStep<?> step, Consumer<Object> previous) { + previous.accept(RRuntime.INT_NA); + previous.accept(RRuntime.DOUBLE_NA); + previous.accept(RRuntime.LOGICAL_NA); + previous.accept(RRuntime.STRING_NA); + previous.accept(RRuntime.LOGICAL_NA); + previous.accept(RDataFactory.createComplex(RRuntime.COMPLEX_NA_REAL_PART, 0)); + + return s -> { + previous.accept(s); + }; + } + + @Override + public Consumer<Object> visit(BoxPrimitiveStep<?> step, Consumer<Object> previous) { + previous.accept(0); + previous.accept(0.0); + previous.accept((byte) 0); + previous.accept(""); + previous.accept(RNull.instance); + previous.accept(RMissing.instance); + + return s -> { + previous.accept(s); + }; + } + + @Override + public Consumer<Object> visit(AttributableCoercionStep<?> step, Consumer<Object> previous) { + previous.accept(RDataFactory.createInternalEnv()); + return s -> { + previous.accept(s); + }; + } + + @Override + public Consumer<Object> visit(MapToValue<?, ?> mapper, Consumer<Object> previous) { + return s -> { + // no inverse mapping for constants + }; + } + + @Override + public Consumer<Object> visit(MapByteToBoolean mapper, Consumer<Object> previous) { + return s -> { + previous.accept(RRuntime.asLogical((Boolean) s)); + }; + } + + @Override + public Consumer<Object> visit(MapDoubleToInt mapper, Consumer<Object> previous) { + return s -> { + previous.accept(((Integer) s).doubleValue()); + }; + } + + @Override + public Consumer<Object> visit(MapToCharAt mapper, Consumer<Object> previous) { + previous.accept(sampleString(mapper.getIndex()) + (char) mapper.getDefaultValue()); + return s -> { + previous.accept(("" + (char) s)); + }; + } + + // Filter visitor + + @Override + @SuppressWarnings("rawtypes") + public Consumer<Object> visit(TypeFilter<?, ?> filter, Consumer<Object> previous) { + Class<?>[] filterTypes = new Class[]{filter.getType1(), filter.getType2()}; + Set<?> samples = CastUtils.sampleValuesForClasses(filterTypes); + for (Object s : samples) { + previous.accept(s); + } + // a negative sample + previous.accept(RNull.instance); + + return s -> { + if (s instanceof VectorPlaceholder) { + previous.accept(CastUtils.vectorOfSize(filter.getType1(), ((VectorPlaceholder) s).size)); + } else { + previous.accept(s); + } + }; + } + + @Override + public Consumer<Object> visit(RTypeFilter<?> filter, Consumer<Object> previous) { + Class<?>[] cls = CastUtils.rTypeToClasses(filter.getType()); + if (cls != null) { + TypeFilter<?, ?> tf = cls.length == 1 ? new TypeFilter<>(cls[0]) : new TypeFilter<>(cls[0], cls[1]); + visit(tf, previous); + } + + return s -> { + previous.accept(s); + }; + } + + @Override + public Consumer<Object> visit(CompareFilter<?> filter, Consumer<Object> previous) { + Consumer<Object> comparisonConsumer = filter.getSubject().accept(this, filter.getOperation(), previous); + + return s -> { + comparisonConsumer.accept(s); + }; + } + + @Override + public Consumer<Object> visit(AndFilter<?, ?> filter, Consumer<Object> previous) { + Consumer<Object> leftConsumer = filter.getLeft().accept(this, s -> previous.accept(s)); + Consumer<Object> rightConsumer = filter.getRight().accept(this, s -> leftConsumer.accept(s)); + + return s -> { + rightConsumer.accept(s); + }; + } + + @Override + public Consumer<Object> visit(OrFilter<?> filter, Consumer<Object> previous) { + Consumer<Object> leftConsumer = filter.getLeft().accept(this, s -> previous.accept(s)); + Consumer<Object> rightConsumer = filter.getRight().accept(this, s -> leftConsumer.accept(s)); + + return s -> { + rightConsumer.accept(s); + }; + } + + @Override + public Consumer<Object> visit(NotFilter<?> filter, Consumer<Object> previous) { + Consumer<Object> notConsumer = filter.getFilter().accept(this, s -> previous.accept(s)); + + return s -> { + notConsumer.accept(s); + }; + } + + @Override + public Consumer<Object> visit(MatrixFilter<?> filter, Consumer<Object> previous) { + return s -> { + previous.accept(s); + }; + } + + @Override + public Consumer<Object> visit(DoubleFilter filter, Consumer<Object> previous) { + return s -> { + previous.accept(s); + }; + } + + @Override + public Consumer<Object> visit(NullFilter filter, Consumer<Object> previous) { + previous.accept(RNull.instance); + + return s -> { + previous.accept(s); + }; + } + + @Override + public Consumer<Object> visit(MissingFilter filter, Consumer<Object> previous) { + previous.accept(RMissing.instance); + + return s -> { + previous.accept(s); + }; + } + + // Subject of comparison visitor + + @Override + public Consumer<Object> visit(ScalarValue scalarValue, byte operation, Consumer<Object> previous) { + previous.accept(scalarValue.value); + return s -> { + previous.accept(s); + }; + } + + @Override + public Consumer<Object> visit(NATest naTest, byte operation, Consumer<Object> previous) { + switch (naTest.type) { + case Integer: + previous.accept(RRuntime.INT_NA); + break; + case Double: + previous.accept(RRuntime.DOUBLE_NA); + break; + case Logical: + previous.accept(RRuntime.LOGICAL_NA); + break; + case Character: + previous.accept(RRuntime.STRING_NA); + break; + case Complex: + previous.accept(RDataFactory.createComplex(RRuntime.COMPLEX_NA_REAL_PART, 0)); + break; + default: + throw RInternalError.shouldNotReachHere(); + } + return s -> { + previous.accept(s); + }; + } + + @Override + public Consumer<Object> visit(StringLength stringLength, byte operation, Consumer<Object> previous) { + previous.accept(sampleString(stringLength.length)); + // a negative sample + previous.accept(sampleString(stringLength.length + 1)); + + return s -> { + previous.accept(s); + }; + } + + private static String sampleString(int len) { + if (len < 0) { + return null; + } else if (len == 0) { + return ""; + } else { + char[] ch = new char[len]; + Arrays.fill(ch, 'a'); + return String.valueOf(ch); + } + } + + @Override + public Consumer<Object> visit(VectorSize vectorSize, byte operation, Consumer<Object> previous) { + int s = vectorSize.size; + switch (operation) { + case CompareFilter.EQ: + previous.accept(new VectorPlaceholder(s)); + // a negative sample + previous.accept(new VectorPlaceholder(s + 1)); + break; + case CompareFilter.GT: + previous.accept(new VectorPlaceholder(s + 1)); + // a negative sample + previous.accept(new VectorPlaceholder(s)); + break; + case CompareFilter.LT: + previous.accept(new VectorPlaceholder(s - 1)); + // a negative sample + previous.accept(new VectorPlaceholder(s)); + break; + case CompareFilter.GE: + previous.accept(new VectorPlaceholder(s)); + // a negative sample + previous.accept(new VectorPlaceholder(s - 1)); + break; + case CompareFilter.LE: + previous.accept(new VectorPlaceholder(s)); + // a negative sample + previous.accept(new VectorPlaceholder(s + 1)); + break; + default: + throw RInternalError.shouldNotReachHere(); + } + + return sample -> { + previous.accept(sample); + }; + } + + @Override + public Consumer<Object> visit(ElementAt elementAt, byte operation, Consumer<Object> previous) { + RAbstractVector vec = CastUtils.fillVector(elementAt.type, elementAt.index + 1, elementAt.value, true); + previous.accept(vec); + + // a negative sample + vec = CastUtils.fillVector(elementAt.type, elementAt.index, elementAt.value, true); + previous.accept(vec); + + return s -> { + if (s instanceof VectorPlaceholder) { + VectorPlaceholder vectorPlaceholder = (VectorPlaceholder) s; + if (elementAt.index < vectorPlaceholder.size) { + previous.accept(CastUtils.fillVector(elementAt.type, vectorPlaceholder.size, elementAt.value, true)); + } else { + previous.accept(s); + } + } else { + previous.accept(s); + } + }; + } + + @Override + public Consumer<Object> visit(Dim dim, byte operation, Consumer<Object> previous) { + return s -> { + previous.accept(s); + }; + } + + private static final class VectorPlaceholder { + final int size; + + VectorPlaceholder(int size) { + this.size = size; + } + } + +} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java index 5905be7bfb65ea815020bdf2e812a8e2e8ba3700..9b512143f74f997f6f45efe9cf6276c6a1729a0d 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java @@ -69,7 +69,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; * mx --J @'-Dgraal.Dump=HighTier:1 -Dgraal.MethodFilter=*TestCasts* -Dgraal.TraceTruffleCompilation=true -Dgraal.PrintBackendCFG=false' junits --tests TestCasts * * of course, Graal needs to be imported for this to work: - * DEFAULT_DYNAMIC_IMPORTS=graal-core (or graal-enterprise) + * DEFAULT_DYNAMIC_IMPORTS=compiler (or graal-enterprise) */ public class TestCasts extends TestBase { @@ -82,6 +82,7 @@ public class TestCasts extends TestBase { private boolean isCompiled = false; @Child protected T node; + @SuppressWarnings("deprecation") protected TestRootNode(String name, T node) { super(RContext.getRForeignAccessFactory().getTruffleLanguage(), RSyntaxNode.INTERNAL, descriptor); this.name = name; @@ -150,7 +151,7 @@ public class TestCasts extends TestBase { @Override protected Object execute(VirtualFrame frame, Object value) { // use "new Integer(...)" to avoid boxing logic - return new Integer((int) node.execute(value)); + return new Integer((int) node.doCast(value)); } } testCompilation(new Object[]{1, 2, 3}, new Root("FirstInteger")); @@ -171,7 +172,7 @@ public class TestCasts extends TestBase { @Override protected Object execute(VirtualFrame frame, Object value) { - int result = (int) node.execute(constant); + int result = (int) node.doCast(constant); CompilerAsserts.compilationConstant(result); return null; } @@ -191,7 +192,7 @@ public class TestCasts extends TestBase { @Override protected Object execute(VirtualFrame frame, Object value) { - Object res = node.execute(value); + Object res = node.doCast(value); return res; } } @@ -209,7 +210,7 @@ public class TestCasts extends TestBase { @Override protected Object execute(VirtualFrame frame, Object value) { - Object res = node.execute(value); + Object res = node.doCast(value); return res; } } @@ -227,7 +228,7 @@ public class TestCasts extends TestBase { @Override protected Object execute(VirtualFrame frame, Object value) { - Object res = node.execute(value); + Object res = node.doCast(value); return res; } } @@ -248,7 +249,7 @@ public class TestCasts extends TestBase { @Override protected Object execute(VirtualFrame frame, Object value) { - Object res = node.execute(value); + Object res = node.doCast(value); if (mustBeResultCompilationConstant) { CompilerAsserts.compilationConstant(res); } @@ -272,7 +273,7 @@ public class TestCasts extends TestBase { @Override protected Object execute(VirtualFrame frame, Object value) { - int result = (int) node.execute(constant); + int result = (int) node.doCast(constant); CompilerAsserts.compilationConstant(result); return null; } @@ -293,7 +294,7 @@ public class TestCasts extends TestBase { @Override protected Object execute(VirtualFrame frame, Object value) { - int result = (int) node.execute(constant); + int result = (int) node.doCast(constant); CompilerAsserts.compilationConstant(result); return null; } @@ -315,8 +316,8 @@ public class TestCasts extends TestBase { @Override protected Object execute(VirtualFrame frame, Object value) { - // return node.execute(value); - Object result = node.execute(constant); + // return node.doCast(value); + Object result = node.doCast(constant); CompilerAsserts.compilationConstant(result); return null; } @@ -340,7 +341,7 @@ public class TestCasts extends TestBase { @Override protected Object execute(VirtualFrame frame, Object value) { @SuppressWarnings("unused") - Object res = node.execute(value); + Object res = node.doCast(value); return null; } } @@ -370,13 +371,13 @@ public class TestCasts extends TestBase { protected Root(String name) { super(name, setupAndGetCast(b -> b.arg(0).mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().mustBe(lengthLte(1)).map( - charAt0(RRuntime.INT_NA)).notNA(100000))); + charAt0(RRuntime.INT_NA)).replaceNA(100000))); } @Override protected Object execute(VirtualFrame frame, Object value) { @SuppressWarnings("unused") - Object res = node.execute(value); + Object res = node.doCast(value); return null; } } @@ -395,7 +396,7 @@ public class TestCasts extends TestBase { @Override protected Object execute(VirtualFrame frame, Object value) { @SuppressWarnings("unused") - Object res = node.execute(value); + Object res = node.doCast(value); return null; } } @@ -414,7 +415,7 @@ public class TestCasts extends TestBase { @Override protected Object execute(VirtualFrame frame, Object value) { @SuppressWarnings("unused") - Object res = node.execute(value); + Object res = node.doCast(value); return null; } } @@ -432,7 +433,7 @@ public class TestCasts extends TestBase { @Override protected Object execute(VirtualFrame frame, Object value) { @SuppressWarnings("unused") - Object res = node.execute(value); + Object res = node.doCast(value); return null; } } @@ -452,7 +453,7 @@ public class TestCasts extends TestBase { @Override protected Object execute(VirtualFrame frame, Object value) { @SuppressWarnings("unused") - Object res = node.execute(value); + Object res = node.doCast(value); return null; } } diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeAndInstanceCheck.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeAndInstanceCheck.java index d9c58b69394b7708052a4b8218d23d3b69771fa1..e5b115a5532ef8067afba1a5de1bbdc17c4e479b 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeAndInstanceCheck.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeAndInstanceCheck.java @@ -28,46 +28,72 @@ import java.util.Optional; import com.oracle.truffle.r.nodes.casts.CastUtils.Cast; import com.oracle.truffle.r.nodes.casts.CastUtils.Cast.Coverage; +import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.nodes.casts.CastUtils.Casts; public interface TypeAndInstanceCheck { boolean isInstance(Object x); + static boolean isInstance(Type t, Object x) { + if (t instanceof Class) { + return ((Class<?>) t).isInstance(x); + } else if (t instanceof TypeAndInstanceCheck) { + return ((TypeAndInstanceCheck) t).isInstance(x); + } else { + throw RInternalError.shouldNotReachHere(); + } + } + Optional<Class<?>> classify(); + Type normalize(); + static Coverage coverage(Type from, Type to, boolean includeImplicits) { - assert (to instanceof Not || to instanceof Class); assert (from instanceof Not || from instanceof Class); + assert (to instanceof Not || to instanceof Class); if (Not.negateType(to).equals(from)) { return Coverage.none; } - boolean toPositive = !Not.isNegative(to); boolean fromPositive = !Not.isNegative(from); - Class<?> positiveToCls = (Class<?>) CastUtils.Casts.boxType(Not.getPositiveType(to)); - Class<?> positiveFromCls = (Class<?>) CastUtils.Casts.boxType(Not.getPositiveType(from)); - + boolean toPositive = !Not.isNegative(to); + Type posFrom = Not.getPositiveType(from); + Type posTo = Not.getPositiveType(to); Cast.Coverage positiveCoverage; - if (((Class<?>) positiveToCls).isAssignableFrom(positiveFromCls)) { - positiveCoverage = Cast.Coverage.full; - } else if (((Class<?>) positiveFromCls).isAssignableFrom(positiveToCls)) { - positiveCoverage = Cast.Coverage.partial; - } else if (positiveToCls.isInterface() && (positiveFromCls.isInterface() || !(Modifier.isFinal(positiveFromCls.getModifiers()) || !Modifier.isAbstract(positiveFromCls.getModifiers())))) { - positiveCoverage = Cast.Coverage.potential; - } else if (positiveFromCls.isInterface() && (positiveToCls.isInterface() || !(Modifier.isFinal(positiveToCls.getModifiers()) || !Modifier.isAbstract(positiveToCls.getModifiers())))) { - positiveCoverage = Cast.Coverage.potential; + if (posFrom instanceof UpperBoundsConjunction) { + positiveCoverage = ((UpperBoundsConjunction) posFrom).coverageTo(posTo, includeImplicits); + return positiveCoverage.transpose(posFrom, posTo, fromPositive, toPositive); + } else if (posTo instanceof UpperBoundsConjunction) { + positiveCoverage = ((UpperBoundsConjunction) posTo).coverageFrom(UpperBoundsConjunction.fromType(posFrom), includeImplicits); + return positiveCoverage.transpose(posFrom, posTo, fromPositive, toPositive); } else { - positiveCoverage = Cast.Coverage.none; - } + Class<?> positiveFromCls = (Class<?>) CastUtils.Casts.boxType(posFrom); + Class<?> positiveToCls = (Class<?>) CastUtils.Casts.boxType(posTo); - Cast.Coverage implicitCvrg = Cast.Coverage.none; - if (includeImplicits && Casts.hasImplicitCast(positiveFromCls, positiveToCls)) { - implicitCvrg = Cast.Coverage.potential; - } + if (TypeExpr.areMutuallyExclusive(positiveToCls, positiveFromCls)) { + positiveCoverage = Cast.Coverage.none; + } else if (((Class<?>) positiveToCls).isAssignableFrom(positiveFromCls)) { + positiveCoverage = Cast.Coverage.full; + } else if (((Class<?>) positiveFromCls).isAssignableFrom(positiveToCls)) { + positiveCoverage = Cast.Coverage.partial; + } else if (positiveToCls.isInterface() && (positiveFromCls.isInterface() || !(Modifier.isFinal(positiveFromCls.getModifiers()) || !Modifier.isAbstract(positiveFromCls.getModifiers())))) { + positiveCoverage = Cast.Coverage.potential; + } else if (positiveFromCls.isInterface() && (positiveToCls.isInterface() || !(Modifier.isFinal(positiveToCls.getModifiers()) || !Modifier.isAbstract(positiveToCls.getModifiers())))) { + positiveCoverage = Cast.Coverage.potential; + } else { + positiveCoverage = Cast.Coverage.none; + } - positiveCoverage = implicitCvrg.or(positiveCoverage); + Cast.Coverage implicitCvrg = Cast.Coverage.none; + if (includeImplicits && Casts.hasImplicitCast(positiveFromCls, positiveToCls)) { + implicitCvrg = Cast.Coverage.potential; + } + + positiveCoverage = implicitCvrg.or(positiveCoverage); + + return positiveCoverage.transpose(positiveFromCls, positiveToCls, fromPositive, toPositive); + } - return positiveCoverage.transpose(positiveFromCls, positiveToCls, fromPositive, toPositive); } } diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeConjunction.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeConjunction.java deleted file mode 100644 index 6e56be18befc96f63c4996049f47836167f72492..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeConjunction.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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 - * 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.casts; - -import java.lang.reflect.Type; -import java.lang.reflect.WildcardType; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; - -import com.oracle.truffle.r.nodes.casts.CastUtils.Cast.Coverage; - -public final class TypeConjunction implements WildcardType, TypeAndInstanceCheck { - - private final Set<Type> upperBounds; - - TypeConjunction(Set<Type> upperBounds) { - this.upperBounds = new HashSet<>(upperBounds); - } - - public static TypeConjunction create(Type... types) { - Set<Type> upperBounds = Arrays.asList(types).stream().flatMap(t -> (t instanceof TypeConjunction ? ((TypeConjunction) t).upperBounds : Collections.singleton(t)).stream()).collect( - Collectors.toSet()); - return new TypeConjunction(upperBounds); - } - - public static TypeConjunction fromType(Type t) { - if (t instanceof TypeConjunction) { - return (TypeConjunction) t; - } else { - return new TypeConjunction(Collections.singleton(t)); - } - } - - @Override - public Type[] getUpperBounds() { - return upperBounds.toArray(new Type[upperBounds.size()]); - } - - @Override - public Type[] getLowerBounds() { - return new Type[0]; - } - - @Override - public boolean isInstance(Object x) { - return upperBounds.stream().filter(t -> ((TypeAndInstanceCheck) t).isInstance(x)).findAny().isPresent(); - } - - public Coverage coverageFrom(TypeConjunction from, boolean includeImplicits) { - return upperBounds.stream().map(ubt -> from.coverageTo(ubt, includeImplicits)).reduce((res, cvg) -> cvg.and(res)).orElse(Coverage.none); - } - - public Coverage coverageTo(Type to, boolean includeImplicits) { - assert to instanceof Not || to instanceof Class; - return upperBounds.stream().map(ubt -> TypeAndInstanceCheck.coverage(ubt, to, includeImplicits)).reduce( - (res, cvg) -> res == Coverage.none || cvg == Coverage.none ? Coverage.none : cvg.or(res)).orElse(Coverage.none); - } - - @Override - public Optional<Class<?>> classify() { - Set<Class<?>> classes = upperBounds.stream().filter(t -> t instanceof Class<?>).map(t -> (Class<?>) t).collect(Collectors.toSet()); - return classes.size() == 1 ? Optional.of(classes.iterator().next()) : Optional.empty(); - } - - @Override - public String toString() { - return "(? extends " + upperBounds + ")"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((upperBounds == null) ? 0 : upperBounds.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - TypeConjunction other = (TypeConjunction) obj; - return upperBounds.equals(other.upperBounds); - } -} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeExpr.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeExpr.java index 7f8ca9c660e744076e79afa7cdbfd31a236179db..d156a5156a473161b5fb65c563f69794525af66e 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeExpr.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeExpr.java @@ -28,21 +28,70 @@ import java.util.Collections; import java.util.HashSet; import java.util.Optional; import java.util.Set; -import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; import com.oracle.truffle.r.nodes.casts.CastUtils.Cast; +import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; +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.RAbstractRawVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; public final class TypeExpr { public static final TypeExpr ANYTHING = TypeExpr.atom(Object.class); - public static final TypeExpr NOTHING = new TypeExpr(Collections.emptySet()); + public static final TypeExpr NOTHING = new TypeExpr(Collections.emptySet(), Samples.nothing()); - private final Set<Set<? extends Type>> disjNormForm; + private final Set<Set<Type>> disjNormForm; - private TypeExpr(Set<Set<? extends Type>> disjNormForm) { - this.disjNormForm = disjNormForm; + private final Samples<?> samples; + + private static final Set<Set<Class<?>>> mutuallyExclusiveInterfaces = new HashSet<>(); + + static { + registerMutuallyExclusiveInterfaces(RAbstractIntVector.class, RAbstractDoubleVector.class, RAbstractLogicalVector.class, RAbstractComplexVector.class, RAbstractRawVector.class, + RAbstractStringVector.class, RAbstractListVector.class); + } + + private TypeExpr(Set<Set<Type>> disjNormForm, Samples<?> samples) { + // remove contradictions + // Set<Set<Type>> noContra = disjNormForm.stream().filter(conj -> + // !isContradiction(conj)).collect(Collectors.toSet()); + Set<Set<Type>> noContra = disjNormForm.stream().map(conj -> normalizeConjunctionSet(conj)).filter(conj -> !conj.isEmpty()).collect(Collectors.toSet()); + this.disjNormForm = noContra; + this.samples = samples; + } + + public static void registerMutuallyExclusiveInterfaces(Class<?>... types) { + mutuallyExclusiveInterfaces.add(Arrays.stream(types).collect(Collectors.toSet())); + } + + public static Optional<Class<?>> findInMutuallyExclusiveInterfaces(Type t, Set<Class<?>> exclusiveGroup) { + if (t instanceof Class) { + return exclusiveGroup.stream().filter(x -> x.isAssignableFrom((Class<?>) t)).findFirst(); + } else { + return Optional.empty(); + } + } + + public static boolean areMutuallyExclusiveInterfaces(Type t1, Type t2, Set<Class<?>> exclusiveGroup) { + Optional<Class<?>> x1 = findInMutuallyExclusiveInterfaces(t1, exclusiveGroup); + if (!x1.isPresent()) { + return false; + } + Optional<Class<?>> x2 = findInMutuallyExclusiveInterfaces(t2, exclusiveGroup); + if (!x2.isPresent()) { + return false; + } + + return x1.get() != x2.get(); + } + + public static boolean areMutuallyExclusive(Type t1, Type t2) { + return mutuallyExclusiveInterfaces.stream().filter(exclusiveTypesSet -> areMutuallyExclusiveInterfaces(t1, t2, exclusiveTypesSet)).findFirst().isPresent(); } public boolean isNothing() { @@ -59,19 +108,8 @@ public final class TypeExpr { } public static TypeExpr atom(Type t) { - return new TypeExpr(Collections.singleton(Collections.singleton(t))); - } - - public TypeExpr map(Function<Type, Type> typeMapper) { - Set<Set<? extends Type>> newDisjNormForm = disjNormForm.stream().map(conj -> conj.stream().map(typeMapper).collect(Collectors.toSet())).collect(Collectors.toSet()); - return new TypeExpr(newDisjNormForm); - } - - public TypeExpr filter(Predicate<Type> filterPred) { - Set<Set<? extends Type>> newDisjNormForm = disjNormForm.stream().map(conjSet -> { - return conjSet.stream().filter(filterPred).collect(Collectors.toSet()); - }).filter(newConjSet -> !newConjSet.isEmpty()).collect(Collectors.toSet()); - return new TypeExpr(newDisjNormForm); + Samples<?> samples = new Samples<>(t.getTypeName(), Collections.emptySet(), Collections.emptySet(), x -> TypeAndInstanceCheck.isInstance(t, x)); + return new TypeExpr(Collections.singleton(Collections.singleton(t)), samples); } public boolean contains(Type tp) { @@ -79,15 +117,15 @@ public final class TypeExpr { } public TypeExpr or(TypeExpr te) { - Set<Set<? extends Type>> newDisjNormForm = new HashSet<>(this.disjNormForm); + Set<Set<Type>> newDisjNormForm = new HashSet<>(this.disjNormForm); newDisjNormForm.addAll(te.disjNormForm); - return new TypeExpr(newDisjNormForm); + return new TypeExpr(newDisjNormForm, samples.or(te.samples)); } public TypeExpr and(TypeExpr te) { - Set<Set<? extends Type>> newDisjNormForm = new HashSet<>(); + Set<Set<Type>> newDisjNormForm = new HashSet<>(); - for (Set<? extends Type> conj1 : this.disjNormForm) { + for (Set<Type> conj1 : this.disjNormForm) { for (Set<? extends Type> conj2 : te.disjNormForm) { Set<Type> newConj = new HashSet<>(conj1); newConj.addAll(conj2); @@ -95,12 +133,71 @@ public final class TypeExpr { } } - return new TypeExpr(newDisjNormForm); + return new TypeExpr(newDisjNormForm, samples.and(te.samples)); + } + + public TypeExpr lower() { + return lower(new Object()); + } + + public TypeExpr removeWildcards() { + Set<Set<Type>> newDisjNormForm = new HashSet<>(); + + for (Set<Type> conj : this.disjNormForm) { + newDisjNormForm.add(removeWildcardsFromConj(conj)); + } + + return new TypeExpr(newDisjNormForm, samples); + } + + private static Set<Type> removeWildcardsFromConj(Set<Type> conj) { + Set<Type> newConj = new HashSet<>(); + + for (Type t : conj) { + if (t instanceof Not) { + Type neg = ((Not<?>) t).getNegated(); + if (!(neg instanceof UpperBoundsConjunction && ((UpperBoundsConjunction) neg).isWildcard())) { + newConj.add(t); + } // the negation degenerates to Object.class as long as the negated type is a + // wildcard type + } else if (t instanceof UpperBoundsConjunction) { + Set<Type> flattened = ((UpperBoundsConjunction) t).flatten(); + flattened = removeWildcardsFromConj(flattened); + newConj.addAll(flattened); + } else { + newConj.add(t); + } + } + + return newConj; + } + + public TypeExpr positiveSamples(Object... sampleValues) { + return new TypeExpr(disjNormForm, samples.addPositiveSamples(sampleValues)); + } + + public TypeExpr negativeSamples(Object... sampleValues) { + return new TypeExpr(disjNormForm, samples.addNegativeSamples(sampleValues)); + } + + public TypeExpr lower(Object typeRepr) { + Set<Set<Type>> newDisjNormForm = new HashSet<>(); + + for (Set<Type> conj : disjNormForm) { + UpperBoundsConjunction upperConj = UpperBoundsConjunction.create(conj.stream()).asWildcard(typeRepr); + newDisjNormForm.add(Collections.singleton(upperConj)); + } + + return new TypeExpr(newDisjNormForm, samples); } - public static TypeExpr union(Set<? extends Type> types) { - Set<Set<? extends Type>> disjNormForm = types.stream().map(t -> Collections.singleton(t)).collect(Collectors.toSet()); - return new TypeExpr(disjNormForm); + public static TypeExpr union(Set<Type> types) { + Set<Set<Type>> disjNormForm = types.stream().map(t -> Collections.singleton(t)).collect(Collectors.toSet()); + + Predicate<Type> isInstancePred = x -> types.stream().filter(t -> TypeAndInstanceCheck.isInstance(t, x)).findFirst().isPresent(); + @SuppressWarnings({"unchecked", "rawtypes"}) + Samples<?> samples = new Samples(types.toString(), Collections.emptySet(), Collections.emptySet(), isInstancePred); + return new TypeExpr(disjNormForm, samples); } public static TypeExpr union(Class<?>... types) { @@ -116,34 +213,58 @@ public final class TypeExpr { } // !(A.B | C.D) = !(A.B).!(C.D) = (!A | !B).(!C | !D) = !A.!C | !A.!D | !B.!C | !B.!D // !(!A.!B | !C.!D) = !(!A.!B).!(!C.!D) = (A | B).(C | D) = A.C | A.D | B.C | B.D - Set<TypeExpr> asUnions = disjNormForm.stream().map(conj -> union(conj)).collect(Collectors.toSet()); + Set<TypeExpr> asUnions = disjNormForm.stream().map(conj -> union(negateTypes(conj))).collect(Collectors.toSet()); TypeExpr conj = asUnions.stream().reduce((res, te) -> res.and(te)).orElse(NOTHING); - return conj.map(t -> Not.negateType(t)); + return new TypeExpr(conj.disjNormForm, samples.swap()); // add the negated samples } - public Set<Type> normalize() { - return disjNormForm.stream().map(conj -> normalize(conj)).filter(t -> !t.equals(Not.NOTHING)).collect(Collectors.toSet()); + private static Set<Type> negateTypes(Set<Type> types) { + return types.stream().map(t -> Not.negateType(t)).collect(Collectors.toSet()); + } + + public TypeExpr normalize() { + Set<Set<Type>> conjunctionsNormalized = disjNormForm.stream().map(conj -> normalizeConjunctionSet(conj)).filter(t -> !t.equals(Not.NOTHING)).collect(Collectors.toSet()); + return new TypeExpr(conjunctionsNormalized, samples); + } + + public Set<Type> toNormalizedConjunctionSet() { + Set<Type> conjunctionsNormalized = disjNormForm.stream().map(conj -> normalizeConjunction(conj)).filter(t -> !t.equals(Not.NOTHING)).collect(Collectors.toSet()); + return conjunctionsNormalized; + // return squashDisjunctions(conjunctionsNormalized); } public Set<Class<?>> toClasses() { - return normalize().stream().filter(t -> t instanceof Class).map(t -> (Class<?>) t).collect(Collectors.toSet()); + return toNormalizedConjunctionSet().stream().filter(t -> t instanceof Class).map(t -> (Class<?>) t).collect(Collectors.toSet()); + } + + static Type normalizeConjunction(Set<Type> conj) { + Set<Type> moreSpecific = normalizeConjunctionSet(conj); + if (moreSpecific.isEmpty()) { + return Not.NOTHING; + } else if (moreSpecific.size() == 1) { + Type t = moreSpecific.iterator().next(); + return t; + } else { + UpperBoundsConjunction ub = UpperBoundsConjunction.create(moreSpecific.stream()); + return ub; + } } - private static Type normalize(Set<? extends Type> conj) { + static Set<Type> normalizeConjunctionSet(Set<Type> conj) { Type[] conjArray = conj.toArray(new Type[conj.size()]); Set<Type> lessSpecific = new HashSet<>(); for (int i = 0; i < conj.size(); i++) { for (int j = i + 1; j < conj.size(); j++) { - switch (CastUtils.Casts.isConvertible(conjArray[i], conjArray[j], true)) { + switch (CastUtils.Casts.isConvertible(conjArray[i], conjArray[j], false)) { case none: // a contradiction found - return Not.NOTHING; + return Collections.emptySet(); case potential: break; case partial: - if (CastUtils.Casts.isConvertible(conjArray[j], conjArray[i], true) == Cast.Coverage.full) { + if (CastUtils.Casts.isConvertible(conjArray[j], conjArray[i], false) == Cast.Coverage.full) { lessSpecific.add(conjArray[i]); } break; @@ -154,20 +275,30 @@ public final class TypeExpr { } } - HashSet<Type> moreSpecific = new HashSet<>(conj); + Set<Type> moreSpecific = new HashSet<>(conj); moreSpecific.removeAll(lessSpecific); + moreSpecific = moreSpecific.stream().map(t -> t instanceof TypeAndInstanceCheck ? ((TypeAndInstanceCheck) t).normalize() : t).collect(Collectors.toSet()); + return moreSpecific; + } - if (moreSpecific.size() == 1) { - Type t = moreSpecific.iterator().next(); - return t; - } else { - assert !moreSpecific.isEmpty(); - return new TypeConjunction(moreSpecific); + static boolean isContradiction(Set<Type> conj) { + Type[] conjArray = conj.toArray(new Type[conj.size()]); + for (int i = 0; i < conj.size(); i++) { + for (int j = i + 1; j < conj.size(); j++) { + + switch (CastUtils.Casts.isConvertible(conjArray[i], conjArray[j], true)) { + case none: + // a contradiction found + return true; + } + } } + + return false; } public Set<Class<?>> classify() { - return normalize().stream().map(t -> classify(t)).filter(ot -> ot.isPresent()).map(ot -> ot.get()).collect(Collectors.toSet()); + return toNormalizedConjunctionSet().stream().map(t -> classify(t)).filter(ot -> ot.isPresent()).map(ot -> ot.get()).collect(Collectors.toSet()); } private static Optional<Class<?>> classify(Type t) { @@ -180,7 +311,7 @@ public final class TypeExpr { } public boolean isInstance(Object x) { - return normalize().stream().filter(t -> { + return toNormalizedConjunctionSet().stream().filter(t -> { if (t instanceof TypeAndInstanceCheck) { return ((TypeAndInstanceCheck) t).isInstance(x); } else { @@ -191,7 +322,7 @@ public final class TypeExpr { } public Cast.Coverage isConvertibleFrom(Type from, boolean includeImplicits) { - return normalize().stream().map(t -> CastUtils.Casts.isConvertible(from, t, includeImplicits)).reduce((res, cvg) -> res.or(cvg)).orElse(Cast.Coverage.none); + return toNormalizedConjunctionSet().stream().map(t -> CastUtils.Casts.isConvertible(from, t, includeImplicits)).reduce((res, cvg) -> res.or(cvg)).orElse(Cast.Coverage.none); } @Override diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypePredicateArgumentFilterSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypePredicateArgumentFilterSampler.java deleted file mode 100644 index 317f3db07508526b96f83ef4299dc1dc6aadf5f8..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypePredicateArgumentFilterSampler.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2013, 2016, 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.casts; - -import java.util.Arrays; -import java.util.Collections; -import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import com.oracle.truffle.r.nodes.builtin.TypePredicateArgumentFilter; -import com.oracle.truffle.r.nodes.casts.ArgumentFilterSampler.ArgumentTypeFilterSampler; - -public class TypePredicateArgumentFilterSampler<T, R extends T> extends TypePredicateArgumentFilter<T, R> implements ArgumentTypeFilterSampler<T, R> { - - private final TypeExpr trueBranchTypes; - private final Samples<R> samples; - private final String desc; - - @SuppressWarnings("unchecked") - public TypePredicateArgumentFilterSampler(String desc, Predicate<? super T> valuePredicate, Set<? extends R> positiveSamples, Set<?> negativeSamples, Set<Class<?>> allowedTypeSet) { - super(valuePredicate); - - this.trueBranchTypes = allowedTypeSet.isEmpty() ? TypeExpr.ANYTHING : TypeExpr.union(allowedTypeSet); - Predicate<Object> posMembership = x -> trueBranchTypes.isInstance(x) && test((T) x); - this.samples = new Samples<>(desc, positiveSamples, negativeSamples, posMembership); - - assert positiveSamples.stream().allMatch(x -> valuePredicate.test(x)); - - this.desc = desc; - } - - @Override - public TypeExpr trueBranchType() { - return trueBranchTypes; - } - - @Override - public Samples<R> collectSamples(TypeExpr inputType) { - return samples; - } - - @Override - public String toString() { - return desc; - } - - public static <T, R extends T> TypePredicateArgumentFilterSampler<T, R> fromLambda(Predicate<? super T> predicate, Set<? extends R> positiveSamples, Set<?> negativeSamples, - Class<?>... resultClass) { - return new TypePredicateArgumentFilterSampler<>(CastUtils.getPredefStepDesc(), predicate, positiveSamples, negativeSamples, Arrays.asList(resultClass).stream().collect(Collectors.toSet())); - } - - public static <T, R extends T> TypePredicateArgumentFilterSampler<T, R> fromLambda(Predicate<T> predicate, Class<?>... resultClass) { - return new TypePredicateArgumentFilterSampler<>(CastUtils.getPredefStepDesc(), predicate, Collections.emptySet(), Collections.emptySet(), - Arrays.asList(resultClass).stream().collect(Collectors.toSet())); - } - - public static <T, R extends T> TypePredicateArgumentFilterSampler<T, R> fromLambda(Predicate<T> predicate, Set<? extends R> positiveSamples, Set<?> negativeSamples) { - return new TypePredicateArgumentFilterSampler<>(CastUtils.getPredefStepDesc(), predicate, positiveSamples, negativeSamples, Collections.emptySet()); - } - - public static <T, R extends T> TypePredicateArgumentFilterSampler<T, R> fromLambda(Predicate<T> predicate, @SuppressWarnings("unused") Class<R> commonAncestorClass, Set<Class<?>> resultClasses) { - return new TypePredicateArgumentFilterSampler<>(CastUtils.getPredefStepDesc(), predicate, Collections.emptySet(), Collections.emptySet(), resultClasses); - } -} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/UpperBoundsConjunction.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/UpperBoundsConjunction.java new file mode 100644 index 0000000000000000000000000000000000000000..f7475baa48f56cf224f344fb83d2ef52f56e4cbd --- /dev/null +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/UpperBoundsConjunction.java @@ -0,0 +1,211 @@ +/* + * 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 + * 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.casts; + +import java.lang.reflect.Type; +import java.lang.reflect.WildcardType; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.oracle.truffle.r.nodes.casts.CastUtils.Cast.Coverage; +import com.oracle.truffle.r.runtime.RInternalError; + +public final class UpperBoundsConjunction implements WildcardType, TypeAndInstanceCheck { + private static final Type[] EMPTY_TYPES = new Type[0]; + + private final Set<Type> upperBounds; + private final boolean useAsWildcard; + /** + * This typeRepr object represents the wildcard type. Two wildcard types are equivalent if their + * type representations are the same. + */ + private final Object typeRepr; + + UpperBoundsConjunction(Set<Type> upperBounds, boolean useAsWildcard, Object typeRepr) { + this.upperBounds = TypeExpr.normalizeConjunctionSet(upperBounds); + this.useAsWildcard = useAsWildcard; + this.typeRepr = typeRepr == null && useAsWildcard ? new Object() : typeRepr; + } + + public UpperBoundsConjunction asWildcard(Object typeRepres) { + return new UpperBoundsConjunction(upperBounds, true, typeRepres); + } + + private UpperBoundsConjunction removeWildcardAndNormalize() { + return new UpperBoundsConjunction(fromType(TypeExpr.normalizeConjunction(flatten())).upperBounds, false, null); + } + + public Set<Type> flatten() { + Set<Type> flattened = new HashSet<>(); + for (Type t : upperBounds) { + if (t instanceof UpperBoundsConjunction) { + flattened.addAll(((UpperBoundsConjunction) t).flatten()); + } else { + flattened.add(t); + } + } + return flattened; + } + + public static UpperBoundsConjunction create(Type... types) { + Stream<Type> typeStream = Arrays.asList(types).stream(); + return create(typeStream); + } + + public static UpperBoundsConjunction create(Stream<? extends Type> typeStream) { + Set<Type> upperBounds = typeStream.flatMap(t -> ((t instanceof UpperBoundsConjunction && !((UpperBoundsConjunction) t).isWildcard()) ? ((UpperBoundsConjunction) t).upperBounds + : Collections.singleton(t)).stream()).collect(Collectors.toSet()); + return new UpperBoundsConjunction(upperBounds, false, null); + } + + public static UpperBoundsConjunction fromType(Type t) { + if (t instanceof UpperBoundsConjunction) { + return (UpperBoundsConjunction) t; + } else { + return new UpperBoundsConjunction(Collections.singleton(t), false, null); + } + } + + @Override + public Type[] getUpperBounds() { + return upperBounds.toArray(new Type[upperBounds.size()]); + } + + @Override + public Type[] getLowerBounds() { + return useAsWildcard ? EMPTY_TYPES : getUpperBounds(); + } + + public boolean isWildcard() { + return useAsWildcard; + } + + @Override + public boolean isInstance(Object x) { + return upperBounds.stream().filter(t -> ((TypeAndInstanceCheck) t).isInstance(x)).findAny().isPresent(); + } + + public Coverage coverageFrom(UpperBoundsConjunction from, boolean includeImplicits) { + return adjustCoverageFrom(upperBounds.stream().map(ubt -> { + return from.coverageTo(ubt, includeImplicits); + }).reduce((res, cvg) -> cvg.and(res)).orElse(Coverage.none), from); + } + + public Coverage coverageTo(Type to, boolean includeImplicits) { + assert to instanceof Not || to instanceof Class; + return adjustCoverageTo(upperBounds.stream().map(ubt -> { + return TypeAndInstanceCheck.coverage(ubt, to, includeImplicits); + }).reduce((res, cvg) -> res == Coverage.none || cvg == Coverage.none ? Coverage.none : cvg.or(res)).orElse(Coverage.none)); + } + + private Coverage adjustCoverageTo(Coverage cvg) { + if (isWildcard()) { + switch (cvg) { + case full: + return Coverage.full; + case partial: + return Coverage.potential; + case potential: + return Coverage.potential; + case none: + return Coverage.none; + default: + throw RInternalError.shouldNotReachHere(); + } + } else { + return cvg; + } + } + + private Coverage adjustCoverageFrom(Coverage cvg, UpperBoundsConjunction from) { + if (isWildcard()) { + switch (cvg) { + case full: + UpperBoundsConjunction fromNoWildCard = from.removeWildcardAndNormalize(); + UpperBoundsConjunction toNoWildCard = this.removeWildcardAndNormalize(); + + boolean bijection = fromNoWildCard.upperBounds.equals(toNoWildCard.upperBounds); + return bijection ? Coverage.partial : Coverage.potential; + case partial: + return Coverage.partial; + case potential: + return Coverage.potential; + case none: + return Coverage.none; + default: + throw RInternalError.shouldNotReachHere(); + } + } else { + return cvg; + } + } + + @Override + public Type normalize() { + Set<Type> normUpperBounds = fromType(TypeExpr.normalizeConjunction(upperBounds)).upperBounds; + if (!isWildcard() && normUpperBounds.size() == 1) { + return normUpperBounds.iterator().next(); + } else { + return new UpperBoundsConjunction(normUpperBounds, useAsWildcard, typeRepr); + } + } + + @Override + public Optional<Class<?>> classify() { + Set<Class<?>> classes = upperBounds.stream().filter(t -> t instanceof Class<?>).map(t -> (Class<?>) t).collect(Collectors.toSet()); + return classes.size() == 1 ? Optional.of(classes.iterator().next()) : Optional.empty(); + } + + @Override + public String toString() { + return isWildcard() ? "(" + System.identityHashCode(typeRepr) + " extends " + upperBounds + ")" : "(" + upperBounds + ")"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((upperBounds == null) ? 0 : upperBounds.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + UpperBoundsConjunction other = (UpperBoundsConjunction) obj; + return useAsWildcard == other.useAsWildcard && upperBounds.equals(other.upperBounds) && (!useAsWildcard || typeRepr.equals(other.typeRepr)); + } +} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ValuePredicateArgumentFilterSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ValuePredicateArgumentFilterSampler.java deleted file mode 100644 index b8ad3169c5b5799560fd67407ac48bdb5c41a597..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ValuePredicateArgumentFilterSampler.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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 - * 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.casts; - -import java.util.Arrays; -import java.util.Collections; -import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import com.oracle.truffle.r.nodes.builtin.ValuePredicateArgumentFilter; -import com.oracle.truffle.r.nodes.casts.ArgumentFilterSampler.ArgumentValueFilterSampler; - -public class ValuePredicateArgumentFilterSampler<T> extends ValuePredicateArgumentFilter<T> implements ArgumentValueFilterSampler<T> { - - private final TypeExpr trueBranchTypes; - private final Samples<T> samples; - private final String desc; - - @SuppressWarnings("unchecked") - public ValuePredicateArgumentFilterSampler(String desc, Predicate<? super T> valuePredicate, Set<? extends T> positiveSamples, Set<? extends T> negativeSamples, Set<Class<?>> allowedTypeSet) { - super(valuePredicate); - - this.trueBranchTypes = allowedTypeSet.isEmpty() ? TypeExpr.ANYTHING : TypeExpr.union(allowedTypeSet); - Predicate<Object> posMembership = x -> trueBranchTypes.isInstance(x) && test((T) x); - this.samples = new Samples<>(desc, positiveSamples, negativeSamples, posMembership); - - assert positiveSamples.stream().allMatch(x -> valuePredicate.test(x)); - - this.desc = desc; - } - - @Override - public TypeExpr trueBranchType() { - return trueBranchTypes; - } - - @Override - public String toString() { - return desc; - } - - @Override - public Samples<T> collectSamples(TypeExpr inputType) { - return samples; - } - - public static <T> ValuePredicateArgumentFilterSampler<T> fromLambdaWithSamples(Predicate<? super T> predicate, Set<? extends T> positiveSamples, Set<? extends T> negativeSamples, - Class<?> resultClass) { - return new ValuePredicateArgumentFilterSampler<>(CastUtils.getPredefStepDesc(), predicate, positiveSamples, negativeSamples, Collections.singleton(resultClass)); - } - - public static <T> ValuePredicateArgumentFilterSampler<T> fromLambdaWithResTypes(Predicate<T> predicate, Class<?>... resultClass) { - return new ValuePredicateArgumentFilterSampler<>(CastUtils.getPredefStepDesc(), predicate, Collections.emptySet(), Collections.emptySet(), - Arrays.asList(resultClass).stream().collect(Collectors.toSet())); - } - - public static <T> ValuePredicateArgumentFilterSampler<T> fromLambdaWithSamples(Predicate<T> predicate, Set<? extends T> positiveSamples, Set<? extends T> negativeSamples) { - return new ValuePredicateArgumentFilterSampler<>(CastUtils.getPredefStepDesc(), predicate, positiveSamples, negativeSamples, Collections.emptySet()); - } - - public static <T> ValuePredicateArgumentFilterSampler<T> fromLambdaWithSamples(Predicate<T> predicate, Set<T> negativeSamples, - @SuppressWarnings("unused") Class<T> commonAncestorClass, Set<Class<?>> resultClasses) { - return new ValuePredicateArgumentFilterSampler<>(CastUtils.getPredefStepDesc(), predicate, Collections.emptySet(), negativeSamples, resultClasses); - } -} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ValuePredicateArgumentMapperSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ValuePredicateArgumentMapperSampler.java deleted file mode 100644 index 26a790eaf46f06d82b7c29a855c8471c21675ff7..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ValuePredicateArgumentMapperSampler.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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 - * 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.casts; - -import java.util.Collections; -import java.util.Optional; -import java.util.Set; -import java.util.function.Function; -import java.util.function.Predicate; - -import com.oracle.truffle.r.nodes.builtin.ValuePredicateArgumentMapper; - -public class ValuePredicateArgumentMapperSampler<T, R> extends ValuePredicateArgumentMapper<T, R> implements ArgumentMapperSampler<T, R> { - - private final Function<R, T> unmapper; - private final TypeExpr inputTypes; - private final TypeExpr resTypes; - private final String desc; - private final Samples<T> samples; - - public ValuePredicateArgumentMapperSampler(String desc, Function<T, R> mapper, Function<R, T> unmapper, Set<? extends T> positiveSamples, Set<?> negativeSamples, Set<Class<?>> inputTypeSet, - Set<Class<?>> resultTypeSet) { - super(mapper); - this.unmapper = unmapper; - this.inputTypes = inputTypeSet.isEmpty() ? TypeExpr.ANYTHING : TypeExpr.union(inputTypeSet); - this.resTypes = resultTypeSet.isEmpty() ? TypeExpr.ANYTHING : TypeExpr.union(resultTypeSet); - this.desc = desc; - Predicate<Object> posMembership = x -> inputTypes.isInstance(x) && !negativeSamples.contains(x); - this.samples = new Samples<>(desc, positiveSamples, negativeSamples, posMembership); - } - - @Override - public TypeExpr resultTypes(TypeExpr it) { - return resTypes; - } - - @Override - public String toString() { - return desc; - } - - public static <T, R> ValuePredicateArgumentMapperSampler<T, R> fromLambda(Function<T, R> mapper, Function<R, T> unmapper, Class<T> inputClass, Class<R> resultClass) { - return new ValuePredicateArgumentMapperSampler<>(CastUtils.getPredefStepDesc(), mapper, unmapper, Collections.emptySet(), Collections.emptySet(), - inputClass == null ? Collections.emptySet() : Collections.singleton(inputClass), - resultClass == null ? Collections.emptySet() : Collections.singleton(resultClass)); - } - - public static <T, R> ValuePredicateArgumentMapperSampler<T, R> fromLambda(Function<T, R> mapper, Function<R, T> unmapper, Set<? extends T> positiveSamples, Set<? extends T> negativeSamples, - Class<T> inputClass, Class<?> resultClass) { - return new ValuePredicateArgumentMapperSampler<>(CastUtils.getPredefStepDesc(), mapper, unmapper, positiveSamples, negativeSamples, - inputClass == null ? Collections.emptySet() : Collections.singleton(inputClass), - resultClass == null ? Collections.emptySet() : Collections.singleton(resultClass)); - } - - @Override - public Samples<T> collectSamples(Samples<R> downStreamSamples) { - if (unmapper == null) { - return samples; - } else { - Samples<R> filtered = downStreamSamples.filter(x -> resTypes.isInstance(x), x -> resTypes.isInstance(x)); - @SuppressWarnings("unchecked") - Samples<T> unmappedSamples = filtered.map(x -> unmapper.apply(x), x -> unmapper.apply((R) x), - x -> inputTypes.isInstance(x) ? Optional.of(mapper.apply((T) x)) : Optional.empty(), - x -> inputTypes.isInstance(x) ? Optional.of(mapper.apply((T) x)) : Optional.empty()); - - Samples<T> combined = samples.and(unmappedSamples); - return combined; - } - } -} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/VectorPredicateArgumentFilterSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/VectorPredicateArgumentFilterSampler.java deleted file mode 100644 index 8676a5c2b0adbc094bbba2fd7394c6bf420a46b6..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/VectorPredicateArgumentFilterSampler.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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 - * 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.casts; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import com.oracle.truffle.r.nodes.builtin.VectorPredicateArgumentFilter; -import com.oracle.truffle.r.nodes.casts.ArgumentFilterSampler.ArgumentValueFilterSampler; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; - -public class VectorPredicateArgumentFilterSampler<T extends RAbstractVector> extends VectorPredicateArgumentFilter<T> implements ArgumentValueFilterSampler<T> { - - private final String desc; - private final List<Integer> invalidVectorSize; - - public VectorPredicateArgumentFilterSampler(String desc, Predicate<T> valuePredicate, Integer... invalidVectorSize) { - super(valuePredicate); - this.desc = desc; - this.invalidVectorSize = invalidVectorSize == null ? Collections.emptyList() : Arrays.asList(invalidVectorSize); - } - - @SuppressWarnings("unchecked") - private boolean testVector(Object x) { - if (x instanceof RAbstractVector) { - return test((T) x); - } else { - Object v = CastUtils.singletonVector(x); - if (v == RNull.instance || v == RMissing.instance) { - // these values are ignored, they should never appear in a filter or a mapper - return true; - } - return test((T) v); - } - } - - @Override - public String toString() { - return this.desc; - } - - @Override - public Samples<T> collectSamples(TypeExpr inputType) { - Set<RAbstractVector> negSamples = inputType.toClasses().stream().flatMap(vt -> invalidVectorSize.stream().map(sz -> CastUtils.vectorOfSize(vt, sz))).collect(Collectors.toSet()); - - Predicate<Object> posMembership = this::testVector; - final Samples<T> samples = new Samples<>(desc, Collections.emptySet(), negSamples, posMembership); - - return samples; - } - - @Override - public TypeExpr trueBranchType() { - return TypeExpr.ANYTHING; - } -} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java similarity index 93% rename from com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java rename to com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java index 24e9d47732f8070bc3d3abaaa840a2faead9264a..1ae687272d0a714a1bcd32daf5b71b7d34606d71 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java @@ -20,10 +20,10 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.nodes.builtin; +package com.oracle.truffle.r.nodes.castsTests; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.anyValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.anyValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asBoolean; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asInteger; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asIntegerVector; @@ -55,9 +55,9 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lte; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.map; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.mustBe; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.mustNotBeNA; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.not; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notNA; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullConstant; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; @@ -66,7 +66,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElemen import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.squareMatrix; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; -import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -79,15 +78,11 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; -import com.oracle.truffle.r.nodes.builtin.casts.PipelineConfig; import com.oracle.truffle.r.nodes.builtin.casts.fluent.InitialPhaseBuilder; import com.oracle.truffle.r.nodes.builtin.casts.fluent.PreinitialPhaseBuilder; -import com.oracle.truffle.r.nodes.casts.CastNodeSampler; -import com.oracle.truffle.r.nodes.casts.FilterSamplerFactory; -import com.oracle.truffle.r.nodes.casts.MapperSamplerFactory; import com.oracle.truffle.r.nodes.casts.Samples; -import com.oracle.truffle.r.nodes.casts.TypeExpr; import com.oracle.truffle.r.nodes.test.TestUtilities; import com.oracle.truffle.r.nodes.test.TestUtilities.NodeHandle; import com.oracle.truffle.r.nodes.unary.CastNode; @@ -99,6 +94,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.builtins.RBuiltinKind; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RIntSequence; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RList; @@ -130,10 +126,6 @@ public class CastBuilderTest { private PreinitialPhaseBuilder arg; static { - if (TEST_SAMPLING) { - PipelineConfig.setFilterFactory(FilterSamplerFactory.INSTANCE); - PipelineConfig.setMapperFactory(MapperSamplerFactory.INSTANCE); - } CastNode.testingMode(); } @@ -310,7 +302,7 @@ public class CastBuilderTest { @Test public void testSizeWarning() { - arg.defaultWarning(SHOW_CALLER, RError.Message.LENGTH_GT_1).asIntegerVector().shouldBe(singleElement()); + arg.defaultWarning(RError.Message.LENGTH_GT_1).asIntegerVector().shouldBe(singleElement()); RIntVector intVector = RDataFactory.createIntVector(new int[]{1, 2}, true); assertCastWarning(intVector, intVector, RError.Message.LENGTH_GT_1.message); testPipeline(NO_FILTER_EXPECT_EMPTY_SAMPLES); @@ -333,7 +325,7 @@ public class CastBuilderTest { @Test public void testFindFirstWithDefaultError() { // findFirst takes the explicitly specified default error from pipeline - arg.asIntegerVector().defaultError(SHOW_CALLER, RError.Message.SEED_NOT_VALID_INT).findFirst(); + arg.defaultError(RError.Message.SEED_NOT_VALID_INT).asIntegerVector().findFirst(); assertCastFail(RNull.instance, Message.SEED_NOT_VALID_INT.message); } @@ -341,10 +333,10 @@ public class CastBuilderTest { public void testFindFirstWithoutDefaultValue() { arg.asIntegerVector().findFirst(); - assertCastFail(RNull.instance, "argument is of length zero"); - assertCastFail(RMissing.instance, "argument is of length zero"); - assertCastFail(RDataFactory.createIntVector(0), "argument is of length zero"); - assertCastFail(RDataFactory.createList(), "argument is of length zero"); + assertCastFail(RNull.instance, "invalid 'x' argument"); + assertCastFail(RMissing.instance, "invalid 'x' argument"); + assertCastFail(RDataFactory.createIntVector(0), "invalid 'x' argument"); + assertCastFail(RDataFactory.createList(), "invalid 'x' argument"); assertEquals(1, cast(1)); assertEquals(1, cast(RDataFactory.createIntVector(new int[]{1, 2}, true))); assertEquals(1, cast("1")); @@ -353,7 +345,7 @@ public class CastBuilderTest { @Test public void testNoLogicalNA() { - arg.asLogicalVector().findFirst().notNA(RRuntime.LOGICAL_TRUE); + arg.asLogicalVector().findFirst().replaceNA(RRuntime.LOGICAL_TRUE); assertCastPreserves(RRuntime.LOGICAL_FALSE); assertEquals(RRuntime.LOGICAL_TRUE, cast(RRuntime.LOGICAL_NA)); @@ -362,7 +354,7 @@ public class CastBuilderTest { @Test public void testNoIntegerNA() { - arg.asIntegerVector().findFirst().notNA(1); + arg.asIntegerVector().findFirst().replaceNA(1); assertCastPreserves(42); assertEquals(1, cast(RRuntime.INT_NA)); @@ -371,7 +363,7 @@ public class CastBuilderTest { @Test public void testNoDoubleNA() { - arg.asDoubleVector().findFirst().notNA(1.1); + arg.asDoubleVector().findFirst().replaceNA(1.1); assertCastPreserves(3.142); assertEquals(1.1, cast(RRuntime.DOUBLE_NA)); @@ -380,7 +372,7 @@ public class CastBuilderTest { @Test public void testNoStringNA() { - arg.asStringVector().findFirst().notNA("A"); + arg.asStringVector().findFirst().replaceNA("A"); assertCastPreserves("hello world"); assertEquals("A", cast(RRuntime.DOUBLE_NA)); @@ -409,7 +401,7 @@ public class CastBuilderTest { arg.asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean()); assertEquals(Boolean.TRUE, cast(RRuntime.LOGICAL_TRUE)); assertEquals(Boolean.FALSE, cast(RRuntime.LOGICAL_FALSE)); - assertEquals(Boolean.FALSE, cast(RRuntime.LOGICAL_NA)); + assertEquals(Boolean.TRUE, cast(RRuntime.LOGICAL_NA)); assertEquals(Boolean.TRUE, cast(RDataFactory.createLogicalVector(new byte[]{RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE}, true))); assertEquals(Boolean.FALSE, cast(RDataFactory.createLogicalVector(0))); testPipeline(NO_FILTER_EXPECT_EMPTY_SAMPLES); @@ -484,7 +476,7 @@ public class CastBuilderTest { mapIf(instanceOf(RList.class).not(), chain(asLogicalVector()). with(findFirst().logicalElement()). - with(notNA()). + with(mustNotBeNA()). with(map(toBoolean())). with(mustBe(instanceOf(Boolean.class))). with(shouldBe(instanceOf(Object.class))). @@ -550,7 +542,7 @@ public class CastBuilderTest { @Test public void testMessageArgumentAsLambda() { Function<Object, Object> argMsg = name -> "something"; - arg.mustNotBeMissing(SHOW_CALLER, RError.Message.GENERIC, argMsg).mustBe(stringValue(), RError.Message.GENERIC, argMsg); + arg.mustNotBeMissing(RError.Message.GENERIC, argMsg).mustBe(stringValue(), RError.Message.GENERIC, argMsg); assertCastPreserves("abc"); assertCastFail(RMissing.instance, "something"); @@ -573,6 +565,8 @@ public class CastBuilderTest { public void testMustBeSquareMatrix() { arg.asDoubleVector(true, true, true).mustBe(squareMatrix()); + assertCastFail(1.0); + RIntVector vec = RDataFactory.createIntVector(new int[]{0, 1, 2, 3}, true, new int[]{2, 2}); Object res = cast(vec); assertTrue(res instanceof RAbstractDoubleVector); @@ -652,7 +646,7 @@ public class CastBuilderTest { @Test public void testSampleNonNASequence() { - arg.notNA(RError.Message.GENERIC, "Error"); + arg.mustNotBeNA(RError.Message.GENERIC, "Error"); RIntSequence seq = RDataFactory.createIntSequence(1, 1, 1); Object res = cast(seq); Assert.assertSame(seq, res); @@ -660,7 +654,7 @@ public class CastBuilderTest { @Test public void testSampleNAVector() { - arg.notNA("REPLACEMENT"); + arg.replaceNA("REPLACEMENT"); RDoubleVector vec = RDataFactory.createDoubleVector(new double[]{0, 1, RRuntime.DOUBLE_NA, 3}, false); Object res = cast(vec); Assert.assertEquals("REPLACEMENT", res); @@ -683,7 +677,7 @@ public class CastBuilderTest { @Test public void defaultErrorForMustNotBeNull() { - arg.defaultError(RError.SHOW_CALLER, Message.SEED_NOT_VALID_INT).mustNotBeNull(); + arg.defaultError(Message.SEED_NOT_VALID_INT).mustNotBeNull(); assertCastFail(RNull.instance, Message.SEED_NOT_VALID_INT.message); } @@ -866,7 +860,7 @@ public class CastBuilderTest { public void testWarningInElseBranchOfMapIf() { arg.mapIf(numericValue(), chain(asIntegerVector()).with(findFirst().integerElement()).end(), - chain(asIntegerVector()).with(Predef.shouldBe(anyValue().not(), RError.NO_CALLER, RError.Message.NA_INTRODUCED_COERCION)).end()); + chain(asIntegerVector()).with(Predef.shouldBe(anyValue().not(), RError.Message.NA_INTRODUCED_COERCION)).end()); Assert.assertEquals(1, cast(1)); Assert.assertEquals(1, cast("1")); @@ -876,17 +870,29 @@ public class CastBuilderTest { @Test public void testWarningInTrueBranchOfMapIf() { arg.allowNull().mapIf(stringValue(), chain(asStringVector()).with(shouldBe(anyValue().not(), - RError.SHOW_CALLER, RError.Message.NA_INTRODUCED_COERCION)).end(), + RError.Message.NA_INTRODUCED_COERCION)).end(), asIntegerVector()); Assert.assertEquals("1", cast("1")); Assert.assertEquals(RError.Message.NA_INTRODUCED_COERCION.message, CastNode.getLastWarning()); } + private static final RFunction DUMMY_FUNCTION = RDataFactory.createFunction(RFunction.NO_NAME, RFunction.NO_NAME, null, null, null); + + @Test + public void testReturnIfFunction() { + arg.allowNull().returnIf(instanceOf(RFunction.class)).asVector(false); + RFunction f = DUMMY_FUNCTION; + Object o = cast(f); + assertEquals(f, o); + testPipeline(); + } + /** * Casts given object using the configured pipeline in {@link #arg}. */ private Object cast(Object a) { - NodeHandle<CastNode> argCastNodeHandle = TestUtilities.createHandle(getCastNode(), (node, args) -> node.execute(args[0])); + CastNode.clearLastWarning(); + NodeHandle<CastNode> argCastNodeHandle = TestUtilities.createHandle(getCastNode(), (node, args) -> node.doCast(args[0])); return argCastNodeHandle.call(a); } @@ -936,26 +942,16 @@ public class CastBuilderTest { * This tests the pipeline sampling process: all positive samples are successful and all * negative cause an error. */ - private void testPipeline() { + private static void testPipeline() { testPipeline(false); } - private TypeExpr resultTypes() { - CastNodeSampler<CastNode> sampler = CastNodeSampler.createSampler(getCastNode()); - return sampler.resultTypes(); - } - - private void testPipeline(boolean emptyPositiveSamplesAllowed) { + private static void testPipeline(@SuppressWarnings("unused") boolean emptyPositiveSamplesAllowed) { if (!TEST_SAMPLING) { return; } - CastNodeSampler<CastNode> sampler = CastNodeSampler.createSampler(getCastNode()); - Samples<?> samples = sampler.collectSamples(); - if (!emptyPositiveSamplesAllowed) { - Assert.assertFalse(samples.positiveSamples().isEmpty()); - } - testPipeline(samples); + // TODO: } private CastNode getCastNode() { @@ -965,6 +961,7 @@ public class CastBuilderTest { return castNode; } + @SuppressWarnings("unused") private void testPipeline(Samples<?> samples) { if (!TEST_SAMPLING) { return; @@ -992,6 +989,6 @@ public class CastBuilderTest { * Just so that we do not have to build the annotation instance by hand. */ @RBuiltin(kind = RBuiltinKind.PRIMITIVE, name = "forTestingOnly", parameterNames = {"x"}, behavior = RBehavior.PURE) - private static class DummyBuiltin { + static class DummyBuiltin { } } diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastUtilsTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastUtilsTest.java similarity index 99% rename from com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastUtilsTest.java rename to com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastUtilsTest.java index 00c93678c1e568fb04532789c84c1b124bc5354d..6b0be76aefe437245aeba7c56845903f0425c6d0 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastUtilsTest.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastUtilsTest.java @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.nodes.builtin; +package com.oracle.truffle.r.nodes.castsTests; import java.io.Serializable; import java.lang.reflect.Type; diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3cfa577f864115872c0ad8d9f93ce70677ce63d8 --- /dev/null +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java @@ -0,0 +1,509 @@ +/* + * 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.nodes.castsTests; + +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyIntegerVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullConstant; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicIntegerValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicLogicalValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.charAt0; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.dimEq; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleToInt; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.elementAt; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.eq; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.intNA; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.isFractional; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.length; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.map; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.mapIf; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.matrix; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.not; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.squareMatrix; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; +import static com.oracle.truffle.r.nodes.casts.TypeExpr.atom; +import static com.oracle.truffle.r.nodes.casts.MarkLookup.mark; + +import java.lang.reflect.Type; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.oracle.truffle.r.nodes.builtin.CastBuilder; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep; +import com.oracle.truffle.r.nodes.builtin.casts.fluent.PreinitialPhaseBuilder; +import com.oracle.truffle.r.nodes.casts.MarkLookup; +import com.oracle.truffle.r.nodes.casts.ResultTypesAnalyser; +import com.oracle.truffle.r.nodes.casts.TypeExpr; +import com.oracle.truffle.r.nodes.castsTests.CastBuilderTest.DummyBuiltin; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RAttributable; +import com.oracle.truffle.r.runtime.data.RComplex; +import com.oracle.truffle.r.runtime.data.RComplexVector; +import com.oracle.truffle.r.runtime.data.RDouble; +import com.oracle.truffle.r.runtime.data.RDoubleSequence; +import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RIntSequence; +import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RInteger; +import com.oracle.truffle.r.runtime.data.RLogical; +import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RRaw; +import com.oracle.truffle.r.runtime.data.RRawVector; +import com.oracle.truffle.r.runtime.data.RString; +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.RAbstractLogicalVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +public class ResultTypesAnalyserTest { + + private CastBuilder cb; + private PreinitialPhaseBuilder arg; + + @Before + public void setUp() { + MarkLookup.clear(); + cb = new CastBuilder(DummyBuiltin.class.getAnnotation(RBuiltin.class)); + arg = cb.arg("x"); + } + + @After + public void tearDown() { + } + + @Test + public void testAsDoubleVector() { + arg.asDoubleVector(); + assertTypes(RNull.class, RMissing.class, double.class, RDoubleSequence.class, RDoubleVector.class); + } + + @Test + public void testAsIntegerVector() { + arg.asIntegerVector(); + assertTypes(RNull.class, RMissing.class, int.class, RIntSequence.class, RIntVector.class); + } + + @Test + public void testAsLogicalVector() { + arg.asLogicalVector(); + assertTypes(RNull.class, RMissing.class, byte.class, RLogicalVector.class, + RArgsValuesAndNames.class); + } + + @Test + public void testAsStringVector() { + arg.asStringVector(); + assertTypes(RNull.class, RMissing.class, String.class, RStringVector.class); + } + + @Test + public void testAsRawVector() { + arg.asRawVector(); + assertTypes(RNull.class, RMissing.class, RRaw.class, RRawVector.class); + } + + @Test + public void testAsComplexVector() { + arg.asComplexVector(); + assertTypes(RNull.class, RMissing.class, RComplex.class, RComplexVector.class); + } + + @Test + public void testAsVectorPreserveNonVector() { + arg.asVector(true); + assertTypes(RFunction.class, RNull.class, RMissing.class, RAbstractVector.class); + } + + @Test + public void testAsVectorVectorNoPreserveNonVector() { + arg.asVector(false); + assertTypes(RAbstractVector.class, RFunction.class); + } + + @Test + public void testAsAttributableVector() { + arg.asAttributable(false, false, false); + assertTypes(RNull.class, RMissing.class, RAttributable.class); + } + + @Test + public void testBoxPrimitive() { + arg.boxPrimitive(); + TypeExpr expected = TypeExpr.union(RInteger.class, RLogical.class, RDouble.class, RString.class); + expected = expected.or((expected.not().and(atom(String.class).not()).and(atom(Double.class).not()).and(atom(Integer.class).not()).and(atom(Byte.class).not()))); + assertTypes(expected); + } + + @Test + public void testFindFirst() { + arg.asStringVector().findFirst(); + assertTypes(String.class); + } + + @Test + public void testFindFirstOrNull() { + arg.asStringVector().findFirstOrNull(); + assertTypes(RNull.class, String.class); + } + + @Test + public void testFindFirstAfterGenericVector() { + arg.asVector().findFirst(); + assertTypes(atom(RFunction.class).or(atom(RNull.class).or(atom(RMissing.class)).not())); + } + + @Test + public void testMapToValue() { + arg.map(mark(constant(1), "m")); + assertTypes(atom(Integer.class).lower(m("m"))); + } + + @Test + public void testMapByteToBoolean() { + arg.mustBe(atomicLogicalValue()).map(toBoolean()); + assertTypes(Boolean.class); + } + + @Test + public void testMapDoubleToInt() { + arg.mustBe(instanceOf(Double.class)).map(doubleToInt()); + assertTypes(Integer.class); + } + + @Test + public void testMapToCharAt() { + arg.mustBe(instanceOf(String.class)).map(charAt0('A')); + assertTypes(Integer.class); + } + + @Test + public void testTypeFilter() { + arg.mustBe(instanceOf(RString.class)); + assertTypes(RString.class); + } + + @Test + public void testTypeFilterInSeries() { + arg.mustBe(instanceOf(RAbstractVector.class)).mustBe(instanceOf(RString.class)); + assertTypes(RString.class); + } + + @Test + public void testRTypeFilter() { + arg.mustBe(integerValue()); + assertTypes(Integer.class, RAbstractIntVector.class); + } + + @Test + public void testCompareScalarValueFilter() { + arg.mustBe(atomicIntegerValue()).mustBe(mark(eq(1), "x")); + assertWildTypes("x", Integer.class); + } + + @Test + public void testCompareNAValueFilter() { + arg.mustBe(atomicIntegerValue()).mustBe(mark(intNA(), "x")); + assertWildTypes("x", Integer.class); + } + + @Test + public void testCompareStringLengthFilter() { + arg.mustBe(instanceOf(String.class)).mustBe(mark(length(1), "x")); + assertWildTypes("x", String.class); + } + + @Test + public void testCompareVectorSizeFilter() { + arg.mustBe(instanceOf(RStringVector.class)).mustBe(mark(size(1), "x")); + assertWildTypes("x", RStringVector.class); + } + + @Test + public void testCompareElementAtFilter() { + arg.mustBe(instanceOf(RStringVector.class)).mustBe(mark(elementAt(1, "abc"), "x")); + assertWildTypes("x", RStringVector.class); + } + + @Test + public void testCompareDimFilter() { + arg.mustBe(instanceOf(RStringVector.class)).mustBe(mark(dimEq(1, 2), "x")); + assertWildTypes("x", RStringVector.class); + } + + @Test + public void testAndFilter1() { + arg.mustBe(instanceOf(RStringVector.class).and(mark(elementAt(1, "abc"), "x"))); + assertWildTypes("x", RStringVector.class); + } + + @Test + public void testAndFilter2() { + arg.mustBe(instanceOf(RStringVector.class).and(mark(elementAt(1, "abc"), "x1")).and(mark(size(10), "x2"))); + assertTypes(atom(RStringVector.class).lower(m("x1")).and(atom(RStringVector.class).lower(m("x2")))); + } + + @Test + public void testAndAsNegationOfOrFilter() { + // !(!A || !B) = A && B + arg.mustBe(instanceOf(RAbstractStringVector.class).not().or(instanceOf(RAbstractIntVector.class).not()).not()); + assertTypes(atom(RAbstractStringVector.class).and(atom(RAbstractIntVector.class))); + } + + @Test + public void testAndAsNegationOfOrFilter2() { + // !(!A || !B) = A && B + arg.mustBe(instanceOf(RStringVector.class).not().or(instanceOf(RIntVector.class).not()).not()); + // A and B are mutually exclusive, thus their conjunction is empty + assertTypes(TypeExpr.NOTHING); + } + + @Test + public void testOrFilter1() { + arg.mustBe(instanceOf(RStringVector.class).or(nullValue())); + assertTypes(RStringVector.class, RNull.class); + } + + @Test + public void testOrFilter2() { + arg.mustBe(instanceOf(RStringVector.class).or(instanceOf(RIntVector.class).not())); + assertTypes(atom(RStringVector.class).or(atom(RIntVector.class).not())); + } + + @Test + public void testNotOrFilter() { + arg.mustBe(instanceOf(String.class).or(instanceOf(Integer.class)).not()); + assertTypes(atom(String.class).not().and(atom(Integer.class).not())); + } + + @Test + public void testOrAsNegationOfAndFilter() { + // !(!A && !B) = A || B + arg.mustBe(instanceOf(String.class).not().and(instanceOf(Integer.class).not()).not()); + assertTypes(atom(String.class).or(atom(Integer.class))); + } + + @Test + public void testNotFilter1() { + arg.mustBe(instanceOf(RStringVector.class).not()); + assertTypes(atom(RStringVector.class).not()); + } + + @Test + public void testNotFilter2() { + // !(x instanceof RStringVector && "abc".equals(x[1])) + arg.mustBe(instanceOf(RStringVector.class).and(mark(elementAt(1, "abc"), "x")).not()); + assertTypes(atom(RStringVector.class).lower(m("x")).not()); + } + + @Test + public void testNotFilter3() { + // !(x instanceof RStringVector) && (x instanceof RAbstractStringVector) + arg.mustBe(instanceOf(RStringVector.class).not()).mustBe(instanceOf(RAbstractStringVector.class)); + assertTypes(atom(RAbstractStringVector.class).and(atom(RStringVector.class).not())); + } + + @Test + public void testNotFilter4() { + arg.mustBe(instanceOf(RAbstractStringVector.class)).mustBe(mark(elementAt(1, "abc"), "x").not()); + assertTypes(atom(RAbstractStringVector.class).and(atom(RAbstractStringVector.class).lower(m("x")).not())); + } + + @Test + public void testMatrixFilter() { + arg.mustBe(instanceOf(RStringVector.class).and(mark(matrix(), "m"))); + assertTypes(atom(RStringVector.class).lower(m("m"))); + } + + @Test + public void testDoubleFilter() { + arg.mustBe(instanceOf(Double.class).and(mark(isFractional(), "x"))); + assertTypes(atom(Double.class).lower(m("x"))); + } + + @Test + public void testNullFilter() { + arg.mustBe(nullValue().or(stringValue())); + assertTypes(TypeExpr.union(RNull.class, RAbstractStringVector.class, String.class)); + } + + @Test + public void testMissingFilter() { + arg.mustBe(missingValue().or(stringValue())); + assertTypes(TypeExpr.union(RMissing.class, RAbstractStringVector.class, String.class)); + } + + @Test + public void testNonNA() { + arg.mustBe(atomicIntegerValue()).mustNotBeNA(RError.Message.GENERIC, "abc"); + // the type representation of the wildcard result type is the nonNA step + PipelineStep<?, ?> notNAStep = cb.getPipelineBuilders()[0].getFirstStep().getNext(); + assertTypes(atom(Integer.class).lower(notNAStep)); + } + + @Test + public void testCoerceToAttributable() { + arg.asAttributable(false, false, false); + assertTypes(TypeExpr.union(RAttributable.class, RNull.class, RMissing.class)); + } + + @Test + public void testMapIf() { + arg.mapIf(nullValue(), mark(constant(1), "m")); + assertTypes(atom(Integer.class).lower(m("m")).or(atom(RNull.class).not())); + } + + @Test + public void testMapIf2() { + arg.mapIf(nullValue(), mark(constant(1), "m1"), mark(constant("abc"), "m2")); + assertTypes(atom(String.class).lower(m("m2")).or(atom(Integer.class).lower(m("m1")))); + } + + @Test + public void testMapIf3() { + PipelineStep<?, ?> m1 = chain(map(mark(constant(1), "m1"))).end(); + PipelineStep<?, ?> m2 = chain(map(mark(constant("abc"), "m2"))).end(); + arg.mapIf(nullValue(), m1, m2); + assertTypes(atom(String.class).lower(m("m2")).or(atom(Integer.class).lower(m("m1")))); + } + + @Test + public void testMapIf4() { + PipelineStep<?, ?> m1 = chain(map(mark(constant(1), "m1"))).end(); + PipelineStep<?, ?> m2 = chain(mapIf(instanceOf(Double.class), chain(map(mark(constant("abc"), "m2"))).end())).end(); + arg.mapIf(nullValue(), m1, m2); + assertTypes(atom(String.class).lower(m("m2")).or(atom(Integer.class).lower(m("m1")).or(atom(RNull.class).not().and(atom(Double.class).not())))); + } + + @Test + public void testMapIf5() { + PipelineStep<?, ?> m1 = chain(map(mark(constant(1), "m1"))).end(); + PipelineStep<?, ?> m2 = chain(mapIf(instanceOf(Double.class), chain(map(mark(constant("abc"), "m2"))).end())).end(); + arg.mapIf(nullValue(), m1, m2).mapIf(instanceOf(String.class).and(mark(length(10), "m4")), mark(constant((byte) 0), "m3")); + //@formatter:off + assertTypes( + atom(Byte.class).lower(m("m3")). + or(atom(Integer.class).lower(m("m1"))). + or(atom(String.class).lower(m("m2")).and(atom(String.class).lower(m("m4")).not())). + or(atom(Double.class).not().and(atom(RNull.class).not()).and(atom(String.class).lower(m("m4")).not()))); + //@formatter:on + } + + @Test + public void testReturnIf1() { + arg.mapIf(nullValue(), mark(constant(1), "m1"), mark(constant("abc"), "m2")); + assertTypes(atom(String.class).lower(m("m2")).or(atom(Integer.class).lower(m("m1")))); + } + + @Test + public void testReturnIf2() { + arg.returnIf(nullValue(), emptyIntegerVector()).returnIf(missingValue(), emptyIntegerVector()).asIntegerVector(); + assertTypes(atom(int.class).or(atom(RIntSequence.class)).or(atom(RIntVector.class)), true); + } + + @Test + public void testMustNotBeMissingAndBoxPrimitive() { + arg.mustNotBeMissing().returnIf(nullValue(), nullConstant()).mustBe(stringValue()).boxPrimitive().asStringVector(); + assertTypes(atom(RNull.class).or(atom(RStringVector.class)), true); + } + + @Test + public void testAllowMissing() { + arg.allowMissing().mustBe(stringValue()); + assertTypes(RMissing.class, String.class, RAbstractStringVector.class); + } + + @Test + public void testTwoWildcardTypes() { + arg.mustBe((instanceOf(String.class).and(mark(length(10), "l10").or(mark(length(20), "l20"))))); + assertTypes(atom(String.class).lower(m("l10")).or(atom(String.class).lower(m("l20")))); + } + + private static Function<RAbstractDoubleVector, Object> getDimVal(int dim) { + return vec -> vec.getDimensions()[dim]; + } + + @Test + public void testAnalyseRealPipeline() { + arg.mustBe(numericValue()).asVector().mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(not(dimEq(0, 0)), + RError.Message.GENERIC, "'a' is 0-diml").mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_MATRIX_SPEC, "a", getDimVal(0), getDimVal(1)); + assertTypes(TypeExpr.union(RAbstractDoubleVector.class, RAbstractIntVector.class, RAbstractLogicalVector.class), true); + } + + // utilities + + private void assertWildTypes(String mark, Class<?>... expectedTypes) { + TypeExpr expected = TypeExpr.union(expectedTypes).lower(m(mark)); + assertTypes(expected); + } + + private void assertTypes(Class<?>... expectedTypes) { + TypeExpr expected = TypeExpr.union(expectedTypes); + assertTypes(expected); + } + + private void assertTypes(TypeExpr expectedType) { + assertTypes(expectedType, false); + } + + private void assertTypes(TypeExpr expectedType, boolean removeWildcards) { + PipelineStep<?, ?> firstStep = cb.getPipelineBuilders()[0].getFirstStep(); + TypeExpr actualType = ResultTypesAnalyser.analyse(firstStep); + Set<Type> actualNorm = removeWildcards ? actualType.normalize().removeWildcards().toNormalizedConjunctionSet() : actualType.toNormalizedConjunctionSet(); + Set<Type> expectedNorm = expectedType.toNormalizedConjunctionSet(); + Assert.assertEquals(expectedNorm, actualNorm); + } + + /** + * Look up the filter by its mark. + * + * @param mark the mark + * @return the filter + */ + public Object m(String mark) { + Map<String, Object> result = MarkLookup.lookup(cb.getPipelineBuilders()[0].getFirstStep(), mark); + Assert.assertNotNull(result.get(mark)); + return result.get(mark); + } + +} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/SampleCollectorTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/SampleCollectorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..38f3f15c260a340b239dd0f24d2b5aaba0cc0944 --- /dev/null +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/SampleCollectorTest.java @@ -0,0 +1,535 @@ +/* + * 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.nodes.castsTests; + +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicIntegerValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicLogicalValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.charAt0; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.dimEq; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleToInt; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.elementAt; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.eq; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.intNA; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.isFractional; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.length; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.map; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.mapIf; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.matrix; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.hamcrest.CustomMatcher; +import org.hamcrest.Matcher; +import org.hamcrest.core.IsNot; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.oracle.truffle.r.nodes.builtin.CastBuilder; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep; +import com.oracle.truffle.r.nodes.builtin.casts.fluent.PreinitialPhaseBuilder; +import com.oracle.truffle.r.nodes.casts.SamplesCollector; +import com.oracle.truffle.r.nodes.castsTests.CastBuilderTest.DummyBuiltin; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.data.RComplex; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RString; +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 class SampleCollectorTest { + + private CastBuilder cb; + private PreinitialPhaseBuilder arg; + + @Before + public void setUp() { + cb = new CastBuilder(DummyBuiltin.class.getAnnotation(RBuiltin.class)); + arg = cb.arg("x"); + } + + @After + public void tearDown() { + } + + @Test + public void testAsDoubleVector() { + arg.asDoubleVector(); + assertSamples(0.0, Double.NaN, RRuntime.DOUBLE_NA, vector(RType.Double, 0.0), vector(RType.Double, RRuntime.DOUBLE_NA), RNull.instance, RMissing.instance); + } + + @Test + public void testAsIntegerVector() { + arg.asIntegerVector(); + assertSamples(0, RRuntime.INT_NA, vector(RType.Integer, 0), vector(RType.Integer, RRuntime.INT_NA), RNull.instance, RMissing.instance); + } + + @Test + public void testAsLogicalVector() { + arg.asLogicalVector(); + assertAsLogicalVectorSamples(); + } + + private void assertAsLogicalVectorSamples() { + assertSamples(RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA, RRuntime.LOGICAL_TRUE, vector(RType.Logical, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA, RRuntime.LOGICAL_TRUE), RNull.instance, + RMissing.instance); + } + + @Test + public void testAsStringVector() { + arg.asStringVector(); + assertAsStringVectorSamples(); + } + + private void assertAsStringVectorSamples() { + assertSamples("", RRuntime.STRING_NA, vector(RType.Character, ""), vector(RType.Character), vector(RType.Character, RRuntime.STRING_NA), RNull.instance, + RMissing.instance); + } + + @Test + public void testAsRawVector() { + arg.asRawVector(); + assertSamples((byte) 0, vector(RType.Raw, RDataFactory.createRaw((byte) 0)), RNull.instance, RMissing.instance); + } + + @Test + public void testAsComplexVector() { + arg.asComplexVector(); + RComplex na = RComplex.createNA(); + RComplex z = RDataFactory.createComplex(0, 0); + assertSamples(z, na, vector(RType.Complex, z), vector(RType.Complex, na), RNull.instance, RMissing.instance); + } + + @Test + public void testAsVectorPreserveNonVector() { + arg.asVector(true); + assertSamples(); + } + + @Test + public void testAsVectorVectorNoPreserveNonVector() { + arg.asVector(false); + assertSamples(); + } + + @Test + public void testAsAttributableVector() { + arg.asAttributable(false, false, false); + assertSamples(); + } + + @Test + public void testBoxPrimitive() { + arg.boxPrimitive(); + assertSamples(); + } + + @Test + public void testFindFirst() { + arg.asStringVector().findFirst(); + assertAsStringVectorSamples(); + } + + @Test + public void testFindFirstOrNull() { + arg.asStringVector().findFirstOrNull(); + assertAsStringVectorSamples(); + } + + @Test + public void testFindFirstAfterGenericVector() { + arg.asVector().findFirst(); + assertSamples(); + } + + @Test + public void testMapToValue() { + arg.map(constant(1)); + assertSamples(RNull.instance, RMissing.instance); + } + + @Test + public void testMapByteToBoolean() { + arg.mustBe(atomicLogicalValue()).map(toBoolean()); + assertSamples(RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA, RRuntime.LOGICAL_TRUE, RNull.instance, RMissing.instance); + } + + @Test + public void testMapDoubleToInt() { + arg.mustBe(instanceOf(Double.class)).map(doubleToInt()); + assertSamples(0.0, RRuntime.DOUBLE_NA, RNull.instance, RMissing.instance); + } + + @Test + public void testMapToCharAt() { + arg.mustBe(instanceOf(String.class)).map(charAt0('A')); + assertSamples("A", RRuntime.STRING_NA, RNull.instance, RMissing.instance); + } + + @Test + public void testTypeFilter() { + arg.mustBe(instanceOf(String.class)); + assertSamples("", RRuntime.STRING_NA, RNull.instance, RMissing.instance); + } + + @Test + public void testTypeFilterInSeries() { + arg.mustBe(instanceOf(RAbstractVector.class)).mustBe(instanceOf(RString.class)); + assertSamples(vector(RType.Character, ""), vector(RType.Character, RRuntime.STRING_NA), RNull.instance, RMissing.instance); + } + + @Test + public void testRTypeFilter() { + arg.mustBe(integerValue()); + assertSamples(0, RRuntime.INT_NA, vector(RType.Integer, 0), vector(RType.Integer, RRuntime.INT_NA), RNull.instance, RMissing.instance); + } + + @Test + public void testCompareScalarValueFilter() { + arg.mustBe(atomicIntegerValue()).mustBe(eq(100)); + assertSamples(100, RNull.instance, RMissing.instance); + } + + @Test + public void testCompareNAValueFilter() { + arg.mustBe(atomicIntegerValue()).mustBe(intNA()); + assertSamples(RRuntime.INT_NA, RNull.instance, RMissing.instance); + } + + @Test + public void testCompareStringLengthFilter() { + arg.mustBe(instanceOf(String.class)).mustBe(length(5)); + assertSamples(stringOfLength(5), RNull.instance, RMissing.instance); + } + + @Test + public void testCompareVectorSizeFilter() { + arg.mustBe(instanceOf(RStringVector.class)).mustBe(size(10)); + assertSamples(vectorOfSize(RType.Character, 10), RNull.instance, RMissing.instance); + } + + @Test + public void testCompareElementAtFilter() { + arg.mustBe(instanceOf(RStringVector.class)).mustBe(elementAt(3, "abc")); + assertSamples(vectorOfSize(RType.Character, 4), vector(RType.Character, "abc"), RNull.instance, RMissing.instance); + } + + @Test + public void testCompareDimFilter() { + arg.mustBe(instanceOf(RStringVector.class)).mustBe(dimEq(1, 2)); + assertSamples(RNull.instance, RMissing.instance); + } + + @Test + public void testAndFilter1() { + arg.mustBe(instanceOf(RStringVector.class).and(elementAt(3, "xyz"))); + assertSamples(vectorOfSize(RType.Character, 4), vector(RType.Character, "xyz"), RNull.instance, RMissing.instance); + } + + @Test + public void testAndFilter2() { + arg.mustBe(instanceOf(RStringVector.class).and(elementAt(3, "xyz")).and(size(10))); + assertSamples(vectorOfSize(RType.Character, 10), vector(RType.Character, "xyz"), RNull.instance, RMissing.instance); + } + + @Test + public void testAndAsNegationOfOrFilter() { + // !(!A || !B) = A && B + arg.mustBe(instanceOf(RAbstractStringVector.class).not().or(instanceOf(RAbstractIntVector.class).not()).not()); + assertSamples(vector(RType.Character, ""), vector(RType.Character, nonEmptyString()), vector(RType.Character, RRuntime.STRING_NA), vector(RType.Integer, 0), + vector(RType.Integer, RRuntime.INT_NA), RNull.instance, RMissing.instance); + } + + @Test + public void testAndAsNegationOfOrFilter2() { + // !(!A || !B) = A && B + arg.mustBe(instanceOf(RStringVector.class).not().or(instanceOf(RIntVector.class).not()).not()); + assertSamples(vector(RType.Character, ""), vector(RType.Character, nonEmptyString()), vector(RType.Character, RRuntime.STRING_NA), vector(RType.Integer, 0), + vector(RType.Integer, RRuntime.INT_NA), RNull.instance, RMissing.instance); + } + + @Test + public void testOrFilter1() { + arg.mustBe(instanceOf(RStringVector.class).or(nullValue())); + assertSamples(vector(RType.Character, ""), vector(RType.Character, nonEmptyString()), vector(RType.Character, RRuntime.STRING_NA), RNull.instance, RMissing.instance); + } + + @Test + public void testOrFilter2() { + arg.mustBe(instanceOf(RStringVector.class).or(instanceOf(RIntVector.class).not())); + assertSamples(vector(RType.Character, ""), vector(RType.Character, nonEmptyString()), vector(RType.Character, RRuntime.STRING_NA), vector(RType.Integer, 0), + vector(RType.Integer, RRuntime.INT_NA), RNull.instance, RMissing.instance); + } + + @Test + public void testNotOrFilter() { + arg.mustBe(instanceOf(RStringVector.class).or(instanceOf(RIntVector.class)).not()); + assertSamples(vector(RType.Character, ""), vector(RType.Character, nonEmptyString()), vector(RType.Character, RRuntime.STRING_NA), vector(RType.Integer, 0), + vector(RType.Integer, RRuntime.INT_NA), RNull.instance, RMissing.instance); + } + + @Test + public void testOrAsNegationOfAndFilter() { + // !(!A && !B) = A || B + arg.mustBe(instanceOf(RAbstractStringVector.class).not().and(instanceOf(RAbstractIntVector.class).not()).not()); + assertSamples(vector(RType.Character, ""), vector(RType.Character, nonEmptyString()), vector(RType.Character, RRuntime.STRING_NA), vector(RType.Integer, 0), + vector(RType.Integer, RRuntime.INT_NA), RNull.instance, RMissing.instance); + } + + @Test + public void testNotFilter1() { + arg.mustBe(instanceOf(RStringVector.class).not()); + assertSamples(vector(RType.Character, ""), vector(RType.Character, nonEmptyString()), vector(RType.Character, RRuntime.STRING_NA), RNull.instance, RMissing.instance); + } + + @Test + public void testNotFilter2() { + // !(x instanceof RStringVector && "abc".equals(x[1])) + arg.mustBe(instanceOf(RStringVector.class).and(elementAt(3, "xyz")).not()); + assertSamples(vectorOfSize(RType.Character, 4), vector(RType.Character, "xyz"), RNull.instance, RMissing.instance); + } + + @Test + public void testNotFilter3() { + // !(x instanceof RStringVector) && (x instanceof RAbstractStringVector) + arg.mustBe(instanceOf(RStringVector.class).not()).mustBe(instanceOf(RAbstractStringVector.class)); + assertSamples(vector(RType.Character, ""), vector(RType.Character, nonEmptyString()), vector(RType.Character, RRuntime.STRING_NA), RNull.instance, RMissing.instance); + } + + @Test + public void testNotFilter4() { + arg.mustBe(instanceOf(RAbstractStringVector.class)).mustBe(elementAt(3, "xyz").not()); + assertSamples(vectorOfSize(RType.Character, 4), vector(RType.Character, "xyz"), RNull.instance, RMissing.instance); + } + + @Test + public void testMatrixFilter() { + arg.mustBe(instanceOf(RStringVector.class).and(matrix())); + assertSamples(vector(RType.Character, ""), vector(RType.Character, nonEmptyString()), vector(RType.Character, RRuntime.STRING_NA), RNull.instance, RMissing.instance); + } + + @Test + public void testDoubleFilter() { + arg.mustBe(instanceOf(Double.class).and(isFractional())); + assertSamples(0.0, Double.NaN, RRuntime.DOUBLE_NA, RNull.instance, RMissing.instance); + } + + @Test + public void testNullFilter() { + arg.mustBe(nullValue().or(stringValue())); + assertSamples("", RRuntime.STRING_NA, vector(RType.Character, ""), vector(RType.Character, RRuntime.STRING_NA), RNull.instance, RMissing.instance); + } + + @Test + public void testMissingFilter() { + arg.mustBe(missingValue().or(stringValue())); + assertAsStringVectorSamples(); + } + + @Test + public void testNonNA() { + arg.mustBe(atomicIntegerValue()).mustNotBeNA(RError.Message.GENERIC, "abc"); + assertSamples(RRuntime.STRING_NA); + } + + @Test + public void testMapIf() { + arg.mapIf(nullValue(), constant(1)); + assertSamples(RNull.instance, RMissing.instance); + } + + @Test + public void testMapIf2() { + arg.mapIf(nullValue(), constant(1), constant("abc")); + assertSamples(RNull.instance, RMissing.instance); + } + + @Test + public void testMapIf3() { + PipelineStep<?, ?> m1 = chain(map(constant(1))).end(); + PipelineStep<?, ?> m2 = chain(map(constant("xyz"))).end(); + arg.mapIf(stringValue(), m1, m2); + assertAsStringVectorSamples(); + } + + @Test + public void testMapIf4() { + PipelineStep<?, ?> m1 = chain(map(constant(1))).end(); + PipelineStep<?, ?> m2 = chain(mapIf(instanceOf(Double.class), chain(map(constant("abc"))).end())).end(); + arg.mapIf(nullValue(), m1, m2); + assertSamples(0.0, Double.NaN, RRuntime.DOUBLE_NA, RNull.instance, RMissing.instance); + } + + @Test + public void testMapIf5() { + PipelineStep<?, ?> m1 = chain(map(constant(1))).end(); + PipelineStep<?, ?> m2 = chain(mapIf(instanceOf(Double.class), chain(map(constant("abc"))).end())).end(); + arg.mapIf(nullValue(), m1, m2).mapIf(instanceOf(String.class).and(length(10)), constant((byte) 0)); + assertSamples("", RRuntime.STRING_NA, 0.0, Double.NaN, RRuntime.DOUBLE_NA, RNull.instance, RMissing.instance); + } + + @Test + public void testReturnIf() { + arg.mapIf(nullValue(), constant(1), constant("abc")); + assertSamples(RNull.instance); + } + + @Test + public void testTwoWildcardTypes() { + arg.mustBe((instanceOf(String.class).and(length(10).or(length(20))))); + assertSamples(stringOfLength(10), stringOfLength(20)); + } + + // utilities + + @SuppressWarnings("unchecked") + void assertSamples(Object... expected) { + Set<Object> samples = collectSamples(); + Assert.assertFalse(samples.isEmpty()); + for (Object es : expected) { + if (es instanceof Matcher) { + Assert.assertThat(samples, (Matcher<Set<Object>>) es); + } else { + Assert.assertTrue("Samples must contain " + es, samples.contains(es)); + } + } + } + + Set<Object> collectSamples() { + return SamplesCollector.collect(cb.getPipelineBuilders()[0].getFirstStep()); + } + + static VectorMatcher vector(RType elemType, Object... expectedElements) { + return new VectorMatcher(elemType, expectedElements); + } + + static Matcher<?> nonEmptyString() { + return new IsNot<>(new StringMatcher(0)); + } + + static Matcher<?> stringOfLength(int expectedLenght) { + return new StringMatcher(expectedLenght); + } + + static Matcher<?> vectorOfSize(RType type, int expectedSize) { + return new VectorSizeMatcher(type, expectedSize); + } + + static final class StringMatcher extends CustomMatcher<Set<Object>> { + + final int expectedLength; + + private StringMatcher(int expectedLength) { + super("String of length " + expectedLength + " expected"); + this.expectedLength = expectedLength; + } + + @Override + public boolean matches(Object item) { + @SuppressWarnings("unchecked") + Set<Object> samples = (Set<Object>) item; + return samples.stream().filter(s -> s instanceof String && s.toString().length() == expectedLength).findAny().isPresent(); + } + + } + + static final class VectorSizeMatcher extends CustomMatcher<Set<Object>> { + + final int expectedSize; + final RType type; + + private VectorSizeMatcher(RType type, int expectedSize) { + super("Vector of size " + expectedSize + " expected"); + this.type = type; + this.expectedSize = expectedSize; + } + + @Override + public boolean matches(Object item) { + @SuppressWarnings("unchecked") + Set<Object> samples = (Set<Object>) item; + return samples.stream().filter(s -> s instanceof RAbstractVector && ((RAbstractVector) s).getRType() == type && ((RAbstractVector) s).getLength() == expectedSize).findAny().isPresent(); + } + + } + + static final class VectorMatcher extends CustomMatcher<Set<Object>> { + final RType elemType; + final Object[] expectedElements; + + VectorMatcher(RType elemType, Object... expectedElements) { + super("Expected " + elemType + " vector: " + Arrays.asList(expectedElements)); + this.elemType = elemType; + this.expectedElements = expectedElements; + } + + @Override + public boolean matches(Object item) { + @SuppressWarnings("unchecked") + Set<Object> samples = (Set<Object>) item; + return samples.stream().filter(s -> s instanceof RAbstractVector && elemType.equals(((RAbstractVector) s).getRType()) && contains((RAbstractVector) s)).findAny().isPresent(); + } + + boolean contains(RAbstractVector v) { + return Arrays.stream(expectedElements).allMatch(expected -> contains(v, expected)); + } + + static boolean contains(RAbstractVector v, Object expected) { + if (expected instanceof Matcher) { + Set<Object> vecAsSet = new HashSet<>(); + for (int i = 0; i < v.getLength(); i++) { + vecAsSet.add(v.getDataAtAsObject(i)); + } + return ((Matcher<?>) expected).matches(vecAsSet); + } else { + for (int i = 0; i < v.getLength(); i++) { + if (expected.equals(v.getDataAtAsObject(i))) { + return true; + } + } + } + return false; + } + + } +} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/TypeExprTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/TypeExprTest.java similarity index 58% rename from com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/TypeExprTest.java rename to com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/TypeExprTest.java index b6d7a40bdc34855dcee43e92887d6ac4b8711ed9..c9fa1f4d53d1d7fbaba8aa9e8e1d77466e83ed0b 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/TypeExprTest.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/TypeExprTest.java @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.nodes.builtin; +package com.oracle.truffle.r.nodes.castsTests; import static com.oracle.truffle.r.nodes.casts.Not.negateType; import static com.oracle.truffle.r.nodes.casts.TypeExpr.atom; @@ -36,11 +36,12 @@ import org.junit.Test; import com.oracle.truffle.r.nodes.casts.CastUtils; import com.oracle.truffle.r.nodes.casts.Not; -import com.oracle.truffle.r.nodes.casts.TypeConjunction; import com.oracle.truffle.r.nodes.casts.TypeExpr; +import com.oracle.truffle.r.nodes.casts.UpperBoundsConjunction; import com.oracle.truffle.r.runtime.data.RIntSequence; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RSequence; +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.RAbstractStringVector; @@ -48,14 +49,18 @@ public class TypeExprTest { @Test public void testNormalize() { - Assert.assertEquals(toSet(String.class), union(String.class).normalize()); - Assert.assertEquals(toSet(String.class, Integer.class), union(String.class, Integer.class).normalize()); - Assert.assertEquals(toSet(RIntSequence.class), atom(RIntSequence.class).and(atom(RSequence.class)).normalize()); - Assert.assertEquals(toSet(String.class), atom(String.class).and(atom(RNull.class).not()).normalize()); - Assert.assertEquals(toSet(TypeConjunction.create(negateType(String.class), negateType(Integer.class))), - atom(String.class).not().and(atom(Integer.class).not()).normalize()); - Assert.assertEquals(toSet(), atom(String.class).not().and(atom(String.class)).normalize()); - Assert.assertEquals(toSet(TypeConjunction.create(RAbstractIntVector.class, RAbstractStringVector.class)), atom(RAbstractIntVector.class).and(atom(RAbstractStringVector.class)).normalize()); + Assert.assertEquals(toSet(String.class), union(String.class).toNormalizedConjunctionSet()); + Assert.assertEquals(toSet(String.class, Integer.class), union(String.class, Integer.class).toNormalizedConjunctionSet()); + Assert.assertEquals(toSet(RIntSequence.class), atom(RIntSequence.class).and(atom(RSequence.class)).toNormalizedConjunctionSet()); + Assert.assertEquals(toSet(String.class), atom(String.class).and(atom(RNull.class).not()).toNormalizedConjunctionSet()); + Assert.assertEquals(toSet(UpperBoundsConjunction.create(negateType(String.class), negateType(Integer.class))), + atom(String.class).not().and(atom(Integer.class).not()).toNormalizedConjunctionSet()); + Assert.assertEquals(toSet(), atom(String.class).not().and(atom(String.class)).toNormalizedConjunctionSet()); + Assert.assertEquals(toSet(UpperBoundsConjunction.create(Runnable.class, RAbstractStringVector.class)), + atom(Runnable.class).and(atom(RAbstractStringVector.class)).toNormalizedConjunctionSet()); + Assert.assertEquals(toSet(RAbstractStringVector.class), atom(UpperBoundsConjunction.fromType(RAbstractStringVector.class)).toNormalizedConjunctionSet()); + Assert.assertEquals(toSet(UpperBoundsConjunction.create(RAbstractStringVector.class, Runnable.class)), + atom(UpperBoundsConjunction.fromType(Runnable.class)).and(atom(UpperBoundsConjunction.fromType(RAbstractStringVector.class))).toNormalizedConjunctionSet()); } @Test @@ -74,6 +79,21 @@ public class TypeExprTest { Assert.assertTrue(CastUtils.Casts.existsConvertibleActualType(from, Integer.class, false)); } + @Test + public void testLower() { + TypeExpr te = atom(String.class); + Assert.assertEquals(toSet(UpperBoundsConjunction.fromType(String.class).asWildcard("a")), te.lower("a").toNormalizedConjunctionSet()); + te = atom(String.class).or(atom(RNull.class)); + Assert.assertEquals(toSet(UpperBoundsConjunction.fromType(String.class).asWildcard("a"), UpperBoundsConjunction.fromType(RNull.class).asWildcard("a")), + te.lower("a").toNormalizedConjunctionSet()); + te = atom(Runnable.class).and(atom(RAbstractStringVector.class)); + Set<Type> exp = toSet(UpperBoundsConjunction.create(Runnable.class, RAbstractStringVector.class).asWildcard("a")); + Assert.assertEquals(exp, te.lower("a").toNormalizedConjunctionSet()); + + te = atom(RAbstractIntVector.class).and(atom(RAbstractDoubleVector.class).lower()); + Assert.assertTrue(te.isNothing()); + } + private static Set<Type> toSet(Type... classes) { return new HashSet<>(Arrays.asList(classes)); } diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryArithmeticNodeTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryArithmeticNodeTest.java index 7ba9410133cc0e33392bf4e59cf21fcc370f0d94..6b8438ab473c1843940a5ea26abef1627ddb49be 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryArithmeticNodeTest.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryArithmeticNodeTest.java @@ -22,7 +22,9 @@ */ package com.oracle.truffle.r.nodes.test; +import static com.oracle.truffle.r.nodes.test.TestUtilities.copy; import static com.oracle.truffle.r.nodes.test.TestUtilities.createHandle; +import static com.oracle.truffle.r.nodes.test.TestUtilities.withinTestContext; import static com.oracle.truffle.r.runtime.data.RDataFactory.createDoubleSequence; import static com.oracle.truffle.r.runtime.data.RDataFactory.createDoubleVectorFromScalar; import static com.oracle.truffle.r.runtime.data.RDataFactory.createEmptyComplexVector; @@ -92,8 +94,8 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest { @Theory public void testScalarUnboxing(BinaryArithmeticFactory factory, RScalarVector aOrig, RAbstractVector bOrig) { - RAbstractVector a = aOrig.copy(); - RAbstractVector b = bOrig.copy(); + RAbstractVector a = withinTestContext(() -> aOrig.copy()); + RAbstractVector b = copy(bOrig); // unboxing cannot work if length is 1 assumeThat(b.getLength(), is(1)); @@ -107,8 +109,8 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest { @Theory public void testVectorResult(BinaryArithmeticFactory factory, RAbstractVector aOrig, RAbstractVector bOrig) { - RAbstractVector a = aOrig.copy(); - RAbstractVector b = bOrig.copy(); + RAbstractVector a = copy(aOrig); + RAbstractVector b = copy(bOrig); assumeThat(a, is(not(instanceOf(RScalarVector.class)))); assumeThat(b, is(not(instanceOf(RScalarVector.class)))); assumeArithmeticCompatible(factory, a, b); @@ -124,8 +126,8 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest { @Theory public void testSharing(BinaryArithmeticFactory factory, RAbstractVector aOrig, RAbstractVector bOrig) { - RAbstractVector a = aOrig.copy(); - RAbstractVector b = bOrig.copy(); + RAbstractVector a = copy(aOrig); + RAbstractVector b = copy(bOrig); assumeArithmeticCompatible(factory, a, b); // not part of this test, see #testEmptyArrays @@ -189,7 +191,7 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest { @Theory public void testEmptyArrays(BinaryArithmeticFactory factory, RAbstractVector originalVector) { - RAbstractVector vector = originalVector.copy(); + RAbstractVector vector = withinTestContext(() -> originalVector.copy()); testEmptyArray(factory, vector, createEmptyLogicalVector()); testEmptyArray(factory, vector, createEmptyIntVector()); testEmptyArray(factory, vector, createEmptyDoubleVector()); @@ -199,7 +201,7 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest { @Theory public void testRNullConstantResult(BinaryArithmeticFactory factory, RAbstractVector originalVector) { - RAbstractVector vector = originalVector.copy(); + RAbstractVector vector = withinTestContext(() -> originalVector.copy()); RType type = vector.getRType() == RType.Complex ? RType.Complex : RType.Double; assertThat(executeArithmetic(factory, vector, RNull.instance), isEmptyVectorOf(type)); @@ -213,8 +215,8 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest { @Theory public void testCompleteness(BinaryArithmeticFactory factory, RAbstractVector aOrig, RAbstractVector bOrig) { - RAbstractVector a = aOrig.copy(); - RAbstractVector b = bOrig.copy(); + RAbstractVector a = copy(aOrig); + RAbstractVector b = copy(bOrig); assumeArithmeticCompatible(factory, a, b); // disable division they might produce NA values by division with 0 @@ -239,8 +241,8 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest { assumeArithmeticCompatible(factory, aOrig, bOrig); // we have to e careful not to change mutable vectors - RAbstractVector a = aOrig.copy(); - RAbstractVector b = bOrig.copy(); + RAbstractVector a = copy(aOrig); + RAbstractVector b = copy(bOrig); if (a instanceof RShareable) { assert ((RShareable) a).isTemporary(); ((RShareable) a).incRefCount(); @@ -250,29 +252,29 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest { ((RShareable) b).incRefCount(); } - RVector<?> aMaterialized = a.copy().materialize(); - RVector<?> bMaterialized = b.copy().materialize(); + RVector<?> aMaterialized = withinTestContext(() -> a.copy().materialize()); + RVector<?> bMaterialized = withinTestContext(() -> b.copy().materialize()); aMaterialized.setAttr("a", "a"); bMaterialized.setAttr("b", "b"); if (a.getLength() == 0 || b.getLength() == 0) { - assertAttributes(executeArithmetic(factory, aMaterialized.copy(), bMaterialized.copy())); - assertAttributes(executeArithmetic(factory, a, bMaterialized.copy())); - assertAttributes(executeArithmetic(factory, aMaterialized.copy(), b)); + assertAttributes(executeArithmetic(factory, copy(aMaterialized), copy(bMaterialized))); + assertAttributes(executeArithmetic(factory, a, copy(bMaterialized))); + assertAttributes(executeArithmetic(factory, copy(aMaterialized), b)); } else if (a.getLength() == b.getLength()) { - assertAttributes(executeArithmetic(factory, aMaterialized.copy(), bMaterialized.copy()), "a", "b"); - assertAttributes(executeArithmetic(factory, a, bMaterialized.copy()), "b"); - assertAttributes(executeArithmetic(factory, aMaterialized.copy(), b), "a"); + assertAttributes(executeArithmetic(factory, copy(aMaterialized), copy(bMaterialized)), "a", "b"); + assertAttributes(executeArithmetic(factory, a, copy(bMaterialized)), "b"); + assertAttributes(executeArithmetic(factory, copy(aMaterialized), b), "a"); } else if (a.getLength() > b.getLength()) { - assertAttributes(executeArithmetic(factory, aMaterialized.copy(), bMaterialized.copy()), "a"); - assertAttributes(executeArithmetic(factory, a, bMaterialized.copy())); - assertAttributes(executeArithmetic(factory, aMaterialized.copy(), b), "a"); + assertAttributes(executeArithmetic(factory, copy(aMaterialized), copy(bMaterialized)), "a"); + assertAttributes(executeArithmetic(factory, a, copy(bMaterialized))); + assertAttributes(executeArithmetic(factory, copy(aMaterialized), b), "a"); } else { assert a.getLength() < b.getLength(); - assertAttributes(executeArithmetic(factory, aMaterialized.copy(), bMaterialized.copy()), "b"); - assertAttributes(executeArithmetic(factory, a, bMaterialized.copy()), "b"); - assertAttributes(executeArithmetic(factory, aMaterialized.copy(), b)); + assertAttributes(executeArithmetic(factory, copy(aMaterialized), copy(bMaterialized)), "b"); + assertAttributes(executeArithmetic(factory, a, copy(bMaterialized)), "b"); + assertAttributes(executeArithmetic(factory, copy(aMaterialized), b)); } } @@ -300,7 +302,7 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest { } catch (AssumptionViolatedException e) { continue; } - executeArithmetic(factory, vector.copy(), vector.copy()); + executeArithmetic(factory, copy(vector), copy(vector)); } } @@ -387,6 +389,6 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest { private static NodeHandle<BinaryArithmeticNode> create(BinaryArithmeticFactory factory) { return createHandle(BinaryArithmeticNode.create(factory, null), - (node, args) -> node.executeBuiltin(null, args[0], args[1])); + (node, args) -> node.execute(args[0], args[1])); } } diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryBooleanNodeTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryBooleanNodeTest.java index 5203cde2f69cdcb4ed28b2bf79dfa67dcdc5f81c..cfcc7861680b29e2e988c2029a5235dc044084b5 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryBooleanNodeTest.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryBooleanNodeTest.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.test; +import static com.oracle.truffle.r.nodes.test.TestUtilities.copy; import static com.oracle.truffle.r.nodes.test.TestUtilities.createHandle; import static com.oracle.truffle.r.runtime.data.RDataFactory.createEmptyComplexVector; import static com.oracle.truffle.r.runtime.data.RDataFactory.createEmptyDoubleVector; @@ -57,6 +58,7 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RRaw; import com.oracle.truffle.r.runtime.data.RScalarVector; import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -90,8 +92,8 @@ public class BinaryBooleanNodeTest extends BinaryVectorTest { @Theory public void testScalarUnboxing(BooleanOperationFactory factory, RScalarVector aOrig, RAbstractVector bOrig) { - RAbstractVector a = aOrig.copy(); - RAbstractVector b = bOrig.copy(); + RAbstractVector a = copy(aOrig); + RAbstractVector b = copy(bOrig); // unboxing cannot work if length is 1 assumeThat(b.getLength(), is(1)); @@ -105,8 +107,8 @@ public class BinaryBooleanNodeTest extends BinaryVectorTest { @Theory public void testVectorResult(BooleanOperationFactory factory, RAbstractVector aOrig, RAbstractVector bOrig) { - RAbstractVector a = aOrig.copy(); - RAbstractVector b = bOrig.copy(); + RAbstractVector a = copy(aOrig); + RAbstractVector b = copy(bOrig); assumeThat(a, is(not(instanceOf(RScalarVector.class)))); assumeThat(b, is(not(instanceOf(RScalarVector.class)))); assumeArithmeticCompatible(factory, a, b); @@ -122,8 +124,8 @@ public class BinaryBooleanNodeTest extends BinaryVectorTest { @Theory public void testSharing(BooleanOperationFactory factory, RAbstractVector aOrig, RAbstractVector bOrig) { - RAbstractVector a = aOrig.copy(); - RAbstractVector b = bOrig.copy(); + RAbstractVector a = copy(aOrig); + RAbstractVector b = copy(bOrig); assumeArithmeticCompatible(factory, aOrig, bOrig); // not part of this test, see #testEmptyArrays @@ -193,7 +195,7 @@ public class BinaryBooleanNodeTest extends BinaryVectorTest { @Theory public void testEmptyArrays(BooleanOperationFactory factory, RAbstractVector originalVector) { - RAbstractVector vector = originalVector.copy(); + RAbstractVector vector = copy(originalVector); assumeArithmeticCompatible(factory, vector, createEmptyLogicalVector()); assumeArithmeticCompatible(factory, vector, createEmptyIntVector()); assumeArithmeticCompatible(factory, vector, createEmptyDoubleVector()); @@ -208,7 +210,7 @@ public class BinaryBooleanNodeTest extends BinaryVectorTest { @Theory public void testRNullConstantResult(BooleanOperationFactory factory, RAbstractVector originalVector) { - RAbstractVector vector = originalVector.copy(); + RAbstractVector vector = copy(originalVector); assumeFalse(isLogicOp(factory)); assumeFalse(vector.getRType() == RType.Raw); assertThat(executeArithmetic(factory, vector, RNull.instance), isEmptyVectorOf(RType.Logical)); @@ -223,8 +225,8 @@ public class BinaryBooleanNodeTest extends BinaryVectorTest { @Theory public void testCompleteness(BooleanOperationFactory factory, RAbstractVector aOrig, RAbstractVector bOrig) { - RAbstractVector a = aOrig.copy(); - RAbstractVector b = bOrig.copy(); + RAbstractVector a = copy(aOrig); + RAbstractVector b = copy(bOrig); assumeArithmeticCompatible(factory, a, b); Object result = executeArithmetic(factory, a, b); @@ -248,7 +250,7 @@ public class BinaryBooleanNodeTest extends BinaryVectorTest { } catch (AssumptionViolatedException e) { continue; } - executeArithmetic(factory, vector.copy(), vector.copy()); + executeArithmetic(factory, copy(vector), copy(vector)); } } @@ -274,7 +276,7 @@ public class BinaryBooleanNodeTest extends BinaryVectorTest { } private static boolean isPrimitive(Object result) { - return result instanceof Integer || result instanceof Double || result instanceof Byte || result instanceof RComplex; + return result instanceof Integer || result instanceof Double || result instanceof Byte || result instanceof RComplex || result instanceof RRaw; } private NodeHandle<BinaryBooleanNode> handle; diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java index c6091bd38e4716a8664480efaba6eebb9816433c..809bf71bdebc1e335c4e84b0003c4ee3940b5730 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java @@ -26,6 +26,7 @@ import static org.junit.Assert.fail; import java.io.File; import java.io.IOException; +import java.lang.reflect.Method; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; @@ -43,8 +44,9 @@ import org.junit.Assert; import com.oracle.truffle.api.dsl.UnsupportedSpecializationException; import com.oracle.truffle.api.vm.PolyglotEngine; import com.oracle.truffle.api.vm.PolyglotEngine.Value; -import com.oracle.truffle.r.nodes.casts.CastNodeSampler; +import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineBuilder; import com.oracle.truffle.r.nodes.casts.Samples; +import com.oracle.truffle.r.nodes.casts.SamplesCollector; import com.oracle.truffle.r.nodes.test.RBuiltinDiagnostics.DiagConfig; import com.oracle.truffle.r.nodes.test.RBuiltinDiagnostics.RIntBuiltinDiagFactory; import com.oracle.truffle.r.nodes.test.RBuiltinDiagnostics.SingleBuiltinDiagnostics; @@ -167,7 +169,7 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { // these values are not determined via the pipeline static type analysis config.performPipelineSelfTest = config.missingAndNullSamplesOnly ? false : !Arrays.stream(args).filter(arg -> NO_SELF_TEST_ARG.equals(arg)).findFirst().isPresent(); config.maxSweeps = Arrays.stream(args).filter(arg -> arg.startsWith(MAX_SWEEPS_ARG)).map(x -> Integer.parseInt(x.split("=")[1])).findFirst().orElse(Integer.MAX_VALUE); - return RBuiltinDiagnostics.initDiagConfig(config, args); + return RBuiltinDiagnostics.initDiagConfig(config, args, false); } private static Optional<String> getSweepMode(String[] args) { @@ -202,28 +204,39 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { } } - private final List<Samples<?>> argSamples; private final ChimneySweepingSuite diagSuite; - private final Set<RList> validArgsList; private final RBuiltinKind kind; + private List<Samples<?>> argSamples; + private Set<RList> validArgsList; + private CastNode[] castNodes; + private final Set<List<String>> printedOutputPairs = new HashSet<>(); private final Set<String> printedErrors = new HashSet<>(); private int sweepCounter = 0; ChimneySweeping(ChimneySweepingSuite diagSuite, RIntBuiltinDiagFactory builtinFactory) { super(diagSuite, builtinFactory); + this.diagSuite = diagSuite; + this.kind = builtinFactory.getBuiltinKind(); + } + + @Override + SingleBuiltinDiagnostics init() throws Throwable { + super.init(); + + this.castNodes = builtinFactory.getCastNodes(); print(0, "\n*** Chimney-sweeping of '" + builtinName + "' (" + builtinFactory.getBuiltinNodeClass().getName() + ") ***"); - this.kind = builtinFactory.getBuiltinKind(); - this.diagSuite = diagSuite; this.validArgsList = extractValidArgsForBuiltin(); this.argSamples = createSamples(); + + return this; } @Override - public void diagnoseBuiltin() throws Exception { + public boolean diagnoseBuiltin() throws Exception { // super.diagnoseBuiltin(); if (blacklistedBuiltins.contains(builtinName)) { @@ -231,10 +244,12 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { } else { sweepChimney(); } + + return true; } @Override - protected void diagnosePipeline(int i) { + protected boolean diagnosePipeline(int i) { super.diagnosePipeline(i); print(1, " Samples:"); @@ -243,6 +258,8 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { if (diagSuite.diagConfig.performPipelineSelfTest) { checkPipelines(i); } + + return true; } @SuppressWarnings({"rawtypes", "unchecked"}) @@ -250,6 +267,8 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { DefaultArgsExtractor defArgExt = new DefaultArgsExtractor(diagSuite.fastRSession, msg -> print(1, msg)); Map<String, Samples<?>> defaultArgs = defArgExt.extractDefaultArgs(builtinName); + PipelineBuilder[] plBuilders = casts.getPipelineBuilders(); + List<Samples<?>> as = new ArrayList<>(); for (int i = 0; i < argLength; i++) { Samples samples; @@ -257,18 +276,18 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { if (diagSuite.diagConfig.missingAndNullSamplesOnly) { samples = Samples.anything(RNull.instance).or(Samples.anything(RMissing.instance)); } else { - CastNode cn; - if (i < castNodes.length) { - cn = castNodes[i]; + PipelineBuilder plBuilder; + if (i < plBuilders.length) { + plBuilder = plBuilders[i]; } else { - cn = null; + plBuilder = null; } try { - if (cn == null) { + if (plBuilder == null) { samples = Samples.anything(); } else { - CastNodeSampler<CastNode> sampler = CastNodeSampler.createSampler(cn); - samples = sampler.collectSamples(); + Set<Object> sampleSet = SamplesCollector.collect(plBuilder.getFirstStep()); + samples = new Samples<>("", sampleSet, Collections.emptySet(), x -> sampleSet.contains(x)); } } catch (Exception e) { throw new RuntimeException("Error in sample generation from argument " + i, e); @@ -312,7 +331,7 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { private void testPipeline(CastNode cn, Samples<?> samples) { NodeHandle<CastNode> argCastNodeHandle = TestUtilities.createHandle(cn, (node, args) -> { - return node.execute(args[0]); + return node.doCast(args[0]); }); for (Object sample : samples.positiveSamples()) { @@ -373,7 +392,11 @@ class ChimneySweeping extends SingleBuiltinDiagnostics { private RList evalValidArgs(String argsExpr, PolyglotEngine vm) { try { Value eval = vm.eval(RSource.fromTextInternal(argsExpr, RSource.Internal.UNIT_TEST)); - RList args = (RList) eval.get(); + Object res = eval.get(); + // TODO: do not use reflection here + Method getter = res.getClass().getDeclaredMethod("getDelegate"); + getter.setAccessible(true); + RList args = (RList) getter.invoke(res); return args; } catch (Exception e) { print(1, "Warning: Cannot parse arguments: " + argsExpr); diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java new file mode 100644 index 0000000000000000000000000000000000000000..f7488cc482d14c7b9aaae65320963a2222578ec0 --- /dev/null +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java @@ -0,0 +1,102 @@ +/* + * 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.nodes.test; + +import java.util.Arrays; +import java.util.List; + +import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; + +/** + * This class contains a list of external builtins. + */ +public class ExtBuiltinsList { + + @SuppressWarnings("rawtypes") private static final Class[] builtins = { + com.oracle.truffle.r.nodes.builtin.RInternalCodeBuiltinNode.class, + com.oracle.truffle.r.nodes.objects.NewObjectNodeGen.class, + com.oracle.truffle.r.nodes.objects.GetPrimNameNodeGen.class, + com.oracle.truffle.r.library.utils.TypeConvertNodeGen.class, + com.oracle.truffle.r.library.utils.RprofNodeGen.class, + com.oracle.truffle.r.library.utils.RprofmemNodeGen.class, + com.oracle.truffle.r.library.utils.ObjectSizeNodeGen.class, + com.oracle.truffle.r.library.utils.MenuNodeGen.class, + com.oracle.truffle.r.library.utils.DownloadNodeGen.class, + com.oracle.truffle.r.library.utils.Crc64NodeGen.class, + com.oracle.truffle.r.library.utils.CountFields.class, + com.oracle.truffle.r.library.parallel.ParallelFunctionsFactory.MCIsChildNodeGen.class, + com.oracle.truffle.r.nodes.builtin.base.foreign.WriteTableNodeGen.class, + com.oracle.truffle.r.nodes.builtin.base.foreign.ReadTableHeadNodeGen.class, + com.oracle.truffle.r.nodes.builtin.base.foreign.MakeQuartzDefault.class, + com.oracle.truffle.r.nodes.builtin.base.foreign.Flushconsole.class, + com.oracle.truffle.r.nodes.builtin.base.foreign.FftNodeGen.class, + com.oracle.truffle.r.nodes.builtin.base.foreign.Dqrdc2NodeGen.class, + com.oracle.truffle.r.nodes.builtin.base.foreign.Dqrcf.class, + com.oracle.truffle.r.nodes.builtin.base.foreign.CairoPropsNodeGen.class, + com.oracle.truffle.r.library.tools.ToolsTextFactory.DoTabExpandNodeGen.class, + com.oracle.truffle.r.library.tools.ToolsTextFactory.CodeFilesAppendNodeGen.class, + com.oracle.truffle.r.library.tools.Rmd5NodeGen.class, + com.oracle.truffle.r.library.tools.DirChmodNodeGen.class, + com.oracle.truffle.r.library.tools.C_ParseRdNodeGen.class, + com.oracle.truffle.r.library.stats.WilcoxFreeNode.class, + com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function3_2NodeGen.class, + com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function4_1NodeGen.class, + com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function4_2NodeGen.class, + com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function3_1NodeGen.class, + com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function2_1NodeGen.class, + com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function2_2NodeGen.class, + com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.ApproxTestNodeGen.class, + com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.ApproxNodeGen.class, + com.oracle.truffle.r.library.stats.SplineFunctionsFactory.SplineCoefNodeGen.class, + com.oracle.truffle.r.library.stats.SplineFunctionsFactory.SplineEvalNodeGen.class, + com.oracle.truffle.r.library.stats.SignrankFreeNode.class, + com.oracle.truffle.r.library.stats.RMultinomNodeGen.class, + com.oracle.truffle.r.library.stats.RandFunctionsNodesFactory.RandFunction3NodeGen.class, + com.oracle.truffle.r.library.stats.RandFunctionsNodesFactory.RandFunction2NodeGen.class, + com.oracle.truffle.r.library.stats.RandFunctionsNodesFactory.RandFunction1NodeGen.class, + com.oracle.truffle.r.library.stats.DoubleCentreNodeGen.class, + com.oracle.truffle.r.library.stats.CutreeNodeGen.class, + com.oracle.truffle.r.library.stats.CovcorNodeGen.class, + com.oracle.truffle.r.library.stats.CompleteCases.class, + com.oracle.truffle.r.library.stats.CdistNodeGen.class, + com.oracle.truffle.r.library.stats.BinDistNodeGen.class, + com.oracle.truffle.r.library.methods.SubstituteDirectNodeGen.class, + com.oracle.truffle.r.library.methods.SlotFactory.R_getSlotNodeGen.class, + com.oracle.truffle.r.library.methods.SlotFactory.R_setSlotNodeGen.class, + com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_initMethodDispatchNodeGen.class, + com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_methodsPackageMetaNameNodeGen.class, + com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_getClassFromCacheNodeGen.class, + com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_set_method_dispatchNodeGen.class, + com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_M_setPrimitiveMethodsNodeGen.class, + com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_identCNodeGen.class, + com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_getGenericNodeGen.class, + com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_nextMethodCallNodeGen.class, + com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_externalPtrPrototypeObjectNodeGen.class, + com.oracle.truffle.r.library.stats.deriv.DerivNodeGen.class, + }; + + @SuppressWarnings("unchecked") + public static List<Class<? extends RExternalBuiltinNode>> getBuiltins() { + return Arrays.asList(builtins); + } +} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java index 76fb3d04577b1188b8cbea518df1d6cc276afd4f..e422add155b3d2649d376645b7674fc56ef37b9b 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java @@ -37,11 +37,13 @@ import com.oracle.truffle.r.nodes.builtin.casts.Filter.NullFilter; import com.oracle.truffle.r.nodes.builtin.casts.Filter.OrFilter; import com.oracle.truffle.r.nodes.builtin.casts.Filter.RTypeFilter; import com.oracle.truffle.r.nodes.builtin.casts.Filter.TypeFilter; +import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapByteToBoolean; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep; import com.oracle.truffle.r.nodes.builtin.casts.analysis.ForwardedValuesAnalyser; import com.oracle.truffle.r.nodes.builtin.casts.analysis.ForwardingAnalysisResult; import com.oracle.truffle.r.runtime.RType; @@ -406,4 +408,26 @@ public class ForwardedValuesAnalyserTest { assertFalse(result.isStringForwarded()); assertFalse(result.isMissingForwarded()); } + + @Test + public void testReturnIfWithTrueBranchChain() { + //@formatter:off + PipelineStep<?, ?> findFirstBoolean = new CoercionStep<>(RType.Logical, false).setNext(new FindFirstStep<>(null, Byte.class, null)).setNext(new MapStep<>(new MapByteToBoolean(false))); + PipelineStep<?, ?> firstStep = new MapIfStep<>(new RTypeFilter<>(RType.Logical), // the condition + findFirstBoolean, null, true); + //@formatter:on + + ForwardedValuesAnalyser fwdAn = new ForwardedValuesAnalyser(); + ForwardingAnalysisResult result = fwdAn.analyse(firstStep); + // TODO: change it to the positive assertion when the selected mappers (such as + // MapByteToBoolean) are supported + assertFalse(result.isLogicalForwarded()); + assertTrue(result.logicalForwarded.mapper instanceof MapByteToBoolean); + assertTrue(result.isDoubleForwarded()); + assertTrue(result.isIntegerForwarded()); + assertTrue(result.isNullForwarded()); + assertTrue(result.isStringForwarded()); + assertTrue(result.isMissingForwarded()); + } + } diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java index 11c58387f483582624a1cb35361f476196d500de..444a877bf6a11d8a738e66673aebfcae3bd9d489 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java @@ -25,24 +25,16 @@ package com.oracle.truffle.r.nodes.test; import static junit.framework.TestCase.assertTrue; import static org.junit.Assert.assertEquals; -import java.util.Optional; - import org.junit.Test; -import com.oracle.truffle.r.nodes.builtin.casts.Filter.OrFilter; -import com.oracle.truffle.r.nodes.builtin.casts.Filter.RTypeFilter; import com.oracle.truffle.r.nodes.builtin.casts.Filter.TypeFilter; -import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapByteToBoolean; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep; -import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode; +import com.oracle.truffle.r.nodes.builtin.casts.analysis.ForwardingAnalysisResult; import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineConfigBuilder; -import com.oracle.truffle.r.nodes.unary.BypassNode; -import com.oracle.truffle.r.nodes.unary.BypassNode.BypassIntegerNode; -import com.oracle.truffle.r.nodes.unary.BypassNode.BypassLogicalMapToBooleanNode; import com.oracle.truffle.r.nodes.unary.CastIntegerBaseNode; import com.oracle.truffle.r.nodes.unary.CastLogicalBaseNode; import com.oracle.truffle.r.nodes.unary.CastNode; @@ -60,66 +52,29 @@ import com.oracle.truffle.r.runtime.env.REnvironment; public class PipelineToCastNodeTests { @Test public void asLogicalVector() { - CastNode pipeline = createPipeline(new CoercionStep<>(RType.Logical, false)); - CastNode castNode = assertBypassNode(pipeline); - assertTrue(castNode instanceof CastLogicalBaseNode); + assertTrue(createPipeline(new CoercionStep<>(RType.Logical, false)) instanceof CastLogicalBaseNode); } @Test public void asStringVectorFindFirst() { - CastNode pipeline = createPipeline(new CoercionStep<>(RType.Character, false).setNext(new FindFirstStep<>("hello", String.class, null))); - CastNode chain = assertBypassNode(pipeline); - assertChainedCast(chain, CastStringBaseNode.class, FindFirstNode.class); - FindFirstNode findFirst = (FindFirstNode) ((ChainedCastNode) chain).getSecondCast(); + assertChainedCast(createPipeline(new CoercionStep<>(RType.Character, false).setNext(new FindFirstStep<>("hello", String.class, null))), CastStringBaseNode.class, FindFirstNode.class); + FindFirstNode findFirst = (FindFirstNode) ((ChainedCastNode) createPipeline( + new CoercionStep<>(RType.Character, false).setNext(new FindFirstStep<>("hello", String.class, null)))).getSecondCast(); assertEquals("hello", findFirst.getDefaultValue()); } - @Test - public void optimizeForSingleInteger() { - // should be equivalent of mustBe(integerValue()).asIntegerVector().findFirst() - CastNode pipeline = createPipeline( - new FilterStep<>(new RTypeFilter<>(RType.Integer), null, false).setNext(new CoercionStep<>(RType.Integer, false).setNext(new FindFirstStep<>(null, Integer.class, null)))); - assertBypassNode(pipeline, BypassIntegerNode.class); - } - - @Test - public void optimizeForSingleIntegerWhenNumericFilterIsUsed() { - // should be close to mustBe(numericValue()).asIntegerVector().findFirst() - OrFilter<Object> filter = new OrFilter<>(new RTypeFilter<>(RType.Integer), new RTypeFilter<>(RType.Double)); - CastNode pipeline = createPipeline( - new FilterStep<>(filter, null, false).setNext(new CoercionStep<>(RType.Integer, false).setNext(new FindFirstStep<>(null, Integer.class, null)))); - assertBypassNode(pipeline, BypassIntegerNode.class); - } - - @Test - public void optimizeMapSingleByteToBoolean() { - // should be equivalent of mustBe(integerValue()).asIntegerVector().findFirst() - CastNode pipeline = createPipeline(new CoercionStep<>(RType.Logical, false).setNext(new FindFirstStep<>(null, Byte.class, null).setNext(new MapStep<>(MapByteToBoolean.INSTANCE)))); - assertBypassNode(pipeline, BypassLogicalMapToBooleanNode.class); - } - @Test public void mustBeREnvironmentAsIntegerVectorFindFirst() { - CastNode pipeline = createPipeline(new FilterStep<>(new TypeFilter<>(REnvironment.class), null, false).setNext( - new CoercionStep<>(RType.Integer, false).setNext(new FindFirstStep<>("hello", String.class, null)))); - CastNode chain = assertBypassNode(pipeline); - assertChainedCast(chain, ChainedCastNode.class, FindFirstNode.class); - CastNode next = ((ChainedCastNode) chain).getFirstCast(); + assertChainedCast(createPipeline(new FilterStep<>(new TypeFilter<>(REnvironment.class), null, false).setNext( + new CoercionStep<>(RType.Integer, false).setNext(new FindFirstStep<>("hello", String.class, null)))), ChainedCastNode.class, FindFirstNode.class); + CastNode next = ((ChainedCastNode) createPipeline(new FilterStep<>(new TypeFilter<>(REnvironment.class), null, false).setNext( + new CoercionStep<>(RType.Integer, false).setNext(new FindFirstStep<>("hello", String.class, null))))).getFirstCast(); assertChainedCast(next, FilterNode.class, CastIntegerBaseNode.class); - FindFirstNode findFirst = (FindFirstNode) ((ChainedCastNode) chain).getSecondCast(); + FindFirstNode findFirst = (FindFirstNode) ((ChainedCastNode) createPipeline(new FilterStep<>(new TypeFilter<>(REnvironment.class), null, false).setNext( + new CoercionStep<>(RType.Integer, false).setNext(new FindFirstStep<>("hello", String.class, null))))).getSecondCast(); assertEquals("hello", findFirst.getDefaultValue()); } - private static CastNode assertBypassNode(CastNode node) { - assertTrue(node instanceof BypassNode); - return ((BypassNode) node).getWrappedHead(); - } - - private static CastNode assertBypassNode(CastNode node, Class<?> expectedClass) { - assertTrue(expectedClass.isInstance(node)); - return ((BypassNode) node).getWrappedHead(); - } - private static void assertChainedCast(CastNode node, Class<?> expectedFirst, Class<?> expectedSecond) { assertTrue(node instanceof ChainedCastNode); assertTrue(expectedFirst.isInstance(((ChainedCastNode) node).getFirstCast())); @@ -129,6 +84,6 @@ public class PipelineToCastNodeTests { private static CastNode createPipeline(PipelineStep<?, ?> lastStep) { PipelineConfigBuilder configBuilder = new PipelineConfigBuilder("x"); configBuilder.setValueForwarding(false); - return PipelineToCastNode.convert(configBuilder.build(), lastStep, Optional.empty()); + return PipelineToCastNode.convert(configBuilder.build(), lastStep, ForwardingAnalysisResult.INVALID); } } diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java index e4b307888c9c0fb6bcbc1bca72dd0b34c6a0d82d..2fce7678ee125b824b806395b3ff792a41d5ca73 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java @@ -35,33 +35,38 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.function.Predicate; import java.util.stream.Collectors; +import com.oracle.truffle.api.dsl.GeneratedBy; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts; import com.oracle.truffle.r.nodes.builtin.RBuiltinFactory; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.BasePackage; -import com.oracle.truffle.r.nodes.builtin.casts.PipelineConfig; -import com.oracle.truffle.r.nodes.casts.CastNodeSampler; +import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineBuilder; import com.oracle.truffle.r.nodes.casts.CastUtils; import com.oracle.truffle.r.nodes.casts.CastUtils.Cast; import com.oracle.truffle.r.nodes.casts.CastUtils.Casts; -import com.oracle.truffle.r.nodes.casts.FilterSamplerFactory; -import com.oracle.truffle.r.nodes.casts.MapperSamplerFactory; import com.oracle.truffle.r.nodes.casts.Not; +import com.oracle.truffle.r.nodes.casts.ResultTypesAnalyser; import com.oracle.truffle.r.nodes.casts.TypeExpr; import com.oracle.truffle.r.nodes.test.ChimneySweeping.ChimneySweepingSuite; import com.oracle.truffle.r.nodes.unary.CastNode; +import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.builtins.RBuiltinKind; import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; public class RBuiltinDiagnostics { private static final String OUTPUT_MAX_LEVEL_ARG = "--outMaxLev="; + private static final TypeExpr rmissingType = TypeExpr.atom(RMissing.class); + static class DiagConfig { boolean verbose; boolean ignoreRNull; @@ -70,46 +75,40 @@ public class RBuiltinDiagnostics { int outputMaxLevel; } - static { - PipelineConfig.setFilterFactory(FilterSamplerFactory.INSTANCE); - PipelineConfig.setMapperFactory(MapperSamplerFactory.INSTANCE); - } - - private final DiagConfig diagConfig; + final DiagConfig diagConfig; + int warningCounter = 0; + int reportedBuiltinsCounter = 0; RBuiltinDiagnostics(DiagConfig diagConfig) { this.diagConfig = diagConfig; } - static RBuiltinDiagnostics createRBuiltinDiagnostics(String[] args) { - return new RBuiltinDiagnostics(initDiagConfig(new DiagConfig(), args)); + static RBuiltinDiagnostics createRBuiltinDiagnostics(String[] args, boolean batchDiag) { + return new RBuiltinDiagnostics(initDiagConfig(new DiagConfig(), args, batchDiag)); } - static <C extends DiagConfig> C initDiagConfig(C diagConfig, String[] args) { + static <C extends DiagConfig> C initDiagConfig(C diagConfig, String[] args, boolean batchDiag) { diagConfig.verbose = Arrays.stream(args).filter(arg -> "-v".equals(arg)).findFirst().isPresent(); diagConfig.ignoreRNull = Arrays.stream(args).filter(arg -> "-n".equals(arg)).findFirst().isPresent(); diagConfig.ignoreRMissing = Arrays.stream(args).filter(arg -> "-m".equals(arg)).findFirst().isPresent(); - diagConfig.outputMaxLevel = Arrays.stream(args).filter(arg -> arg.startsWith(OUTPUT_MAX_LEVEL_ARG)).map(x -> Integer.parseInt(x.split("=")[1])).findFirst().orElse(Integer.MAX_VALUE); + diagConfig.outputMaxLevel = Arrays.stream(args).filter(arg -> arg.startsWith(OUTPUT_MAX_LEVEL_ARG)).map(x -> Integer.parseInt(x.split("=")[1])).findFirst().orElse( + batchDiag ? 0 : Integer.MAX_VALUE); return diagConfig; } public static void main(String[] args) throws Throwable { - // TODO: Enable it when the diagnostics is rewritten using CP-IR - if (true) { - System.out.println("Temporarily disabled until the diagnostics is rewritten using CP-IR"); - return; - } - - @SuppressWarnings("unused") - RBuiltinDiagnostics rbDiag = ChimneySweepingSuite.createChimneySweepingSuite(args).orElseGet(() -> createRBuiltinDiagnostics(args)); - List<String> bNames = Arrays.stream(args).filter(arg -> !arg.startsWith("-")).collect(Collectors.toList()); + + RBuiltinDiagnostics rbDiag = ChimneySweepingSuite.createChimneySweepingSuite(args).orElseGet(() -> createRBuiltinDiagnostics(args, bNames.isEmpty())); if (bNames.isEmpty()) { rbDiag.diagnoseAllBuiltins(); } else { + boolean ok = true; for (String bName : bNames) { - rbDiag.diagnoseSingleBuiltin(bName); + ok &= rbDiag.diagnoseSingleBuiltin(bName); } + + System.exit(ok ? 0 : 1); } } @@ -117,49 +116,223 @@ public class RBuiltinDiagnostics { return new SingleBuiltinDiagnostics(this, bf); } - public void diagnoseSingleBuiltin(String builtinName) throws Exception { + public boolean diagnoseSingleBuiltin(String builtinName) throws Exception { + SingleBuiltinDiagnostics diag; + try { + print(0, "Diagnosing '" + builtinName + "' ..."); + + BasePackage bp = new BasePackage(); + RBuiltinFactory bf = bp.lookupByName(builtinName); + RBuiltinDiagFactory bdf; + + if (bf == null) { + Class<?> bltnCls = loadBuiltinClass(toReflClassName(builtinName)); + if (RExternalBuiltinNode.class.isAssignableFrom(bltnCls)) { + bdf = RExtBuiltinDiagFactory.create(bltnCls); + } else { + bdf = new RIntBuiltinDiagFactory(findBuiltInFactory(bltnCls, bp)); + } + } else { + bdf = new RIntBuiltinDiagFactory(bf); + } + + diag = createBuiltinDiagnostics(bdf); + } catch (Throwable t) { + print(0, "Error in initialization of builtin " + builtinName); + t.printStackTrace(); + return false; + } + + boolean ok = true; + try { + ok = diag.init().diagnoseBuiltin(); + + print(1, "Finished"); + print(1, "--------"); + } catch (WarningException e) { + diag.print(0, "Warning: " + e.getMessage()); + ok = false; + } catch (InfoException e) { + print(0, e.getMessage()); + } catch (Throwable e) { + ok = false; + e.printStackTrace(); + } + return ok; + } + + public void diagnoseAllBuiltins() { BasePackage bp = new BasePackage(); - RBuiltinFactory bf = bp.lookupByName(builtinName); - RBuiltinDiagFactory bdf; - if (bf == null) { + + List<Class<? extends RExternalBuiltinNode>> extBltn = ExtBuiltinsList.getBuiltins(); + Collection<RBuiltinFactory> intBltn = bp.getBuiltins().values(); + int nBltn = intBltn.size() + extBltn.size(); + System.out.println("Diagnosing " + nBltn + " builtins (" + intBltn.size() + " internal, " + extBltn.size() + " external)"); + + boolean ok = true; + int errCounter = 0; + + for (RBuiltinFactory bf : intBltn) { + System.out.print("."); + SingleBuiltinDiagnostics diag; try { - bdf = RExtBuiltinDiagFactory.create(builtinName); - } catch (Exception e) { - print(0, "No builtin '" + builtinName + "' found"); - return; + diag = createBuiltinDiagnostics(new RIntBuiltinDiagFactory((bf))); + } catch (WarningException e) { + print(0, "Warning: " + e.getMessage()); + ok = false; + continue; + } catch (InfoException e) { + print(1, e.getMessage()); + continue; + } catch (Throwable t) { + errCounter++; + print(0, "Error in initialization of builtin " + bf.getName()); + t.printStackTrace(); + ok = false; + continue; + } + try { + ok &= diag.init().diagnoseBuiltin(); + } catch (WarningException e) { + diag.print(0, "Warning: " + e.getMessage()); + ok = false; + } catch (InfoException e) { + diag.print(1, e.getMessage()); + } catch (Throwable t) { + errCounter++; + ok = false; + diag.print(0, ""); + t.printStackTrace(); } - } else { - bdf = new RIntBuiltinDiagFactory(bf); } - createBuiltinDiagnostics(bdf).diagnoseBuiltin(); + for (Class<? extends RExternalBuiltinNode> extBltCls : extBltn) { + System.out.print("."); + SingleBuiltinDiagnostics diag; + try { + diag = createBuiltinDiagnostics(RExtBuiltinDiagFactory.create(extBltCls)); + } catch (WarningException e) { + print(0, "Warning: " + e.getMessage()); + ok = false; + continue; + } catch (InfoException e) { + print(1, e.getMessage()); + continue; + } catch (Throwable t) { + errCounter++; + print(0, "Error in initialization of " + extBltCls.getName() + " builtin"); + t.printStackTrace(); + ok = false; + continue; + } + try { + ok &= diag.init().diagnoseBuiltin(); + } catch (WarningException e) { + diag.print(0, "Warning: " + e.getMessage()); + ok = false; + } catch (InfoException e) { + diag.print(1, e.getMessage()); + } catch (Throwable t) { + errCounter++; + ok = false; + diag.print(0, ""); + t.printStackTrace(); + ok = false; + } + } - print(0, "Finished"); - print(0, "--------"); + print(0, "\n\nFinished:"); + print(0, " Total builtins: " + nBltn); + print(0, " Dubious builtins: " + reportedBuiltinsCounter); + print(0, " Clean builtins: " + (nBltn - reportedBuiltinsCounter)); + print(0, " Errors: " + errCounter); + print(0, " Warnings: " + warningCounter); - System.exit(0); + System.exit(ok ? 0 : 1); } - public void diagnoseAllBuiltins() { - BasePackage bp = new BasePackage(); - for (RBuiltinFactory bf : bp.getBuiltins().values()) { - try { - createBuiltinDiagnostics(new RIntBuiltinDiagFactory((bf))).diagnoseBuiltin(); - } catch (Exception e) { - e.printStackTrace(); - print(0, bf.getName() + " failed: " + e.getMessage()); + private static RBuiltinFactory findBuiltInFactory(Class<?> bltnCls, BasePackage bp) { + Optional<RBuiltinFactory> bltnFact = bp.getBuiltins().values().stream().filter(bf -> bf.getBuiltinNodeClass().isAssignableFrom(bltnCls)).findFirst(); + if (bltnFact.isPresent()) { + return bltnFact.get(); + } else { + throw new IllegalArgumentException("No builtin found for class " + bltnCls.getName()); + } + } + + public static Class<?> loadBuiltinClass(String builtinClsName) throws ClassNotFoundException { + Class<?> nodeClass = Class.forName(builtinClsName); + if (!Modifier.isFinal(nodeClass.getModifiers())) { + nodeClass = toNodeGenClass(nodeClass); + if (!Modifier.isFinal(nodeClass.getModifiers())) { + throw new IllegalArgumentException("Invalid external builtin class name: " + builtinClsName); } } - print(0, "Finished"); - print(0, "--------"); + return nodeClass; + } + + private static String toReflClassName(String qualified) { + String[] split = qualified.split("\\."); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < split.length; i++) { + String s = split[i]; + sb.append(s); + if (i < split.length - 1) { + if (Character.isUpperCase(s.charAt(0))) { + sb.append("$"); + } else { + sb.append("."); + } + } + } + return sb.toString(); + } + + private static String toGenNodeName(String name) { + if (name.endsWith("Node")) { + return name + "Gen"; + } else { + return name + "NodeGen"; + } + } + + private static Class<?> toNodeGenClass(Class<?> nodeCls) throws ClassNotFoundException { + String nodeGenClsName; + if (nodeCls.getEnclosingClass() == null) { + nodeGenClsName = toGenNodeName(nodeCls.getName()); + } else { + String enclClsName = nodeCls.getEnclosingClass().getName(); + String enclosingClsSuffix = RBaseNode.class.isAssignableFrom(nodeCls.getEnclosingClass()) ? (enclClsName.endsWith("Node") ? "Gen" : "NodeGen") : "Factory"; + String[] split = nodeCls.getName().split("\\."); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < split.length; i++) { + String s = split[i]; + if (i == split.length - 1) { + String[] lastSplit = s.split("\\$"); + sb.append(lastSplit[0] + enclosingClsSuffix + "$"); + sb.append(toGenNodeName(lastSplit[1])); + } else { + sb.append(s); + } + if (i < split.length - 1) { + sb.append("."); + } + } + nodeGenClsName = sb.toString(); + } - System.exit(0); + return Class.forName(nodeGenClsName); } protected void print(int level, Object x) { + String msg = "" + x; + if (msg.startsWith("Warning:")) { + warningCounter++; + } + if (level <= diagConfig.outputMaxLevel) { - System.out.println(x); + System.out.println(msg); } } @@ -169,35 +342,60 @@ public class RBuiltinDiagnostics { final String builtinName; final int argLength; final String[] parameterNames; - final CastNode[] castNodes; - final List<Method> specMethods; - final List<TypeExpr> argResultSets; - final HashMap<Method, List<Set<Cast>>> convResultTypePerSpec; - final Set<List<Type>> nonCoveredArgsSet; + + NodeWithArgumentCasts.Casts casts; + List<Method> specMethods; + List<TypeExpr> argResultSets; + HashMap<Method, List<Set<Cast>>> convResultTypePerSpec; + Set<List<Type>> nonCoveredArgsSet; SingleBuiltinDiagnostics(RBuiltinDiagnostics diagSuite, RBuiltinDiagFactory builtinFactory) { this.diagSuite = diagSuite; this.builtinFactory = builtinFactory; this.builtinName = builtinFactory.getBuiltinName(); - String[] pn = builtinFactory.getParameterNames(); this.argLength = pn.length; this.parameterNames = Arrays.stream(pn).map(n -> n == null || n.isEmpty() ? null : n).toArray(String[]::new); + } - this.castNodes = getCastNodesFromBuiltin(); + SingleBuiltinDiagnostics init() throws Throwable { + String builtinClassName = builtinFactory.getBuiltinNodeClass().getName(); + // causes the invocation of the static initializer in the builtin node class + Class<?> bltnCls = NodeWithArgumentCasts.Casts.getBuiltinClass(Class.forName(builtinClassName)); - List<TypeExpr> argResultSetsPreliminary = createArgResultSets(); - argResultSets = argResultSetsPreliminary.stream().map(te -> te.filter(t -> { - return !((diagSuite.diagConfig.ignoreRNull && t == RNull.class) || (diagSuite.diagConfig.ignoreRMissing && t == RMissing.class)); - })).collect(Collectors.toList()); + try { + this.casts = builtinFactory.getCasts(); + } catch (RInternalError e) { + // It will be converted into an error after all builtins are fixed + throw new WarningException("Builtin " + builtinClassName + " should declare argument casts or use Casts.noCasts(" + bltnCls.getSimpleName() + ".class)"); + } - this.specMethods = CastUtils.getAnnotatedMethods(builtinFactory.getBuiltinNodeClass(), Specialization.class); + if (this.casts == null || this.casts.declaresNoCasts()) { + throw new InfoException("Builtin " + builtinClassName + " has no-casts"); + } + + argResultSets = createArgResultSets(); + + List<Method> specs = CastUtils.getAnnotatedMethods(builtinFactory.getBuiltinNodeClass(), Specialization.class); + this.specMethods = new ArrayList<>(specs); + // N.B. The fallback method cannot be found by the Fallback annotation since + // this annotation has the CLASS retention policy. Nonetheless, the fallback method can + // be determined throught the fallback node in the generated class. + Optional<Method> fallback = findFallbackMethod(toNodeGenClass(bltnCls)); + if (fallback.isPresent()) { + this.specMethods.add(fallback.get()); + } this.convResultTypePerSpec = createConvResultTypePerSpecialization(); this.nonCoveredArgsSet = combineArguments(); + + return this; } + private boolean headerPrinted; + protected void print(int level, Object x) { + printBuiltinHeader(level); diagSuite.print(level, x); } @@ -232,30 +430,46 @@ public class RBuiltinDiagnostics { return nonCovered; } - public void diagnoseBuiltin() throws Exception { - print(0, "****************************************************************************"); - print(0, "Builtin: " + builtinName + " (" + builtinFactory.getBuiltinNodeClass().getName() + ")"); - print(0, "****************************************************************************"); + public boolean diagnoseBuiltin() throws Exception { + boolean ok = true; - print(0, "Argument cast pipelines binding:"); + print(1, "Argument cast pipelines binding:"); for (int i = 0; i < argLength; i++) { - diagnosePipeline(i); + ok &= diagnosePipeline(i); } - print(0, "\nUnhandled argument combinations: " + nonCoveredArgsSet.size()); - print(0, ""); + print(1, "\nUnhandled argument combinations: " + nonCoveredArgsSet.size()); + print(1, ""); - printDeadSpecs(); + nonCoveredArgsSet.isEmpty(); if (diagSuite.diagConfig.verbose) { for (List<Type> uncoveredArgs : nonCoveredArgsSet) { - print(0, uncoveredArgs.stream().map(t -> typeName(t)).collect(Collectors.toList())); + print(1, uncoveredArgs.stream().map(t -> typeName(t)).collect(Collectors.toList())); } } + print(1, ""); + + ok &= printDeadSpecs(); + + return ok; } - private void printDeadSpecs() { - print(0, "Dead specializations: "); + private void printBuiltinHeader(int level) { + if (!headerPrinted && level <= diagSuite.diagConfig.outputMaxLevel) { + diagSuite.print(level, "\n"); + diagSuite.print(level, "****************************************************************************"); + diagSuite.print(level, "Builtin: " + builtinName + " (" + builtinFactory.getBuiltinNodeClass().getCanonicalName() + ")"); + diagSuite.print(level, "****************************************************************************"); + headerPrinted = true; + diagSuite.reportedBuiltinsCounter++; + } + } + + private boolean printDeadSpecs() { + boolean ok = true; + StringBuilder sb = new StringBuilder(); + int deadSpecCnt = 0; for (Map.Entry<Method, List<Set<Cast>>> resTpPerSpec : convResultTypePerSpec.entrySet()) { List<Set<Cast>> argsCasts = resTpPerSpec.getValue(); List<Integer> missingCasts = new ArrayList<>(); @@ -267,52 +481,98 @@ public class RBuiltinDiagnostics { } if (!missingCasts.isEmpty()) { - print(0, " " + methodName(resTpPerSpec.getKey(), missingCasts)); + sb.append(" " + methodName(resTpPerSpec.getKey(), missingCasts) + "\n"); + deadSpecCnt++; } } - print(0, ""); + ok = deadSpecCnt == 0; + + int logLev = deadSpecCnt == 0 ? 1 : 0; + String msg = deadSpecCnt == 0 ? "Dead specializations: " + deadSpecCnt : "Warning: Dead specializations: " + deadSpecCnt; + print(logLev, msg); + print(logLev, sb.toString()); + + return ok; } - protected void diagnosePipeline(int i) { + protected boolean diagnosePipeline(int i) { + boolean ok = true; + TypeExpr argResultSet = argResultSets.get(i); - print(0, "\n Pipeline for '" + parameterNames[i] + "' (arg[" + i + "]):"); - print(0, " Result types union:"); - Set<Type> argSetNorm = argResultSet.normalize(); - print(0, " " + argSetNorm.stream().map(argType -> typeName(argType)).collect(Collectors.toSet())); - print(0, " Bound result types:"); + + String pipelineHeader = "Pipeline for '" + parameterNames[i] + "' (arg[" + i + "])"; + + StringBuilder sb = new StringBuilder(); + sb.append(" Result types union:").append('\n'); + Set<Type> argSetNorm = argResultSet.toNormalizedConjunctionSet(); + sb.append(" " + argSetNorm.stream().map(argType -> typeName(argType)).collect(Collectors.toSet())).append('\n'); + sb.append(" Bound result types:").append('\n'); final int curParIndex = i; Set<Type> unboundArgTypes = new HashSet<>(argSetNorm); for (Map.Entry<Method, List<Set<Cast>>> entry : convResultTypePerSpec.entrySet()) { Set<Cast> argCastInSpec = entry.getValue().get(i); argCastInSpec.stream().forEach( partialCast -> { - print(0, " " + partialCast.coverage() + " (" + typeName(partialCast.inputType()) + "->" + typeName(partialCast.resultType()) + ")" + " in " + - methodName(entry.getKey(), Collections.singleton(curParIndex))); + sb.append(" " + partialCast.coverage() + " (" + typeName(partialCast.inputType()) + "->" + typeName(partialCast.resultType()) + ")" + " in " + + methodName(entry.getKey(), Collections.singleton(curParIndex))).append('\n'); unboundArgTypes.remove(partialCast.inputType()); }); } - print(0, " Unbound types:"); - print(0, " " + unboundArgTypes.stream().map(argType -> typeName(argType)).collect(Collectors.toSet())); - - } + if (unboundArgTypes.isEmpty()) { + print(1, pipelineHeader); + } else { + ok = false; + print(0, "Warning: " + pipelineHeader); + print(0, " Unbound types: " + unboundArgTypes.stream().map(argType -> typeName(argType)).collect(Collectors.toSet())); + } + print(1, sb.toString()); - private CastNode[] getCastNodesFromBuiltin() { - return builtinFactory.getCasts(); + return ok; } private List<TypeExpr> createArgResultSets() { + Object[] defParams = null; + try { + defParams = builtinFactory.getDefaultParameterValues(); + } catch (Throwable t) { + print(0, "Warning: Cannot obtain default parameter values. Cause: " + t.getMessage()); + if (diagSuite.diagConfig.outputMaxLevel > 0) { + t.printStackTrace(); + } + } + + if (defParams != null && defParams.length > 0 && defParams.length < argLength) { + throw new RInternalError("Builtin " + builtinName + " provides invalid default parameter values"); + } + List<TypeExpr> as = new ArrayList<>(); + PipelineBuilder[] plBuilders = casts.getPipelineBuilders(); for (int i = 0; i < argLength; i++) { - CastNode cn; - if (i < castNodes.length) { - cn = castNodes[i]; + + PipelineBuilder plBuilder; + if (i < plBuilders.length) { + plBuilder = plBuilders[i]; } else { - cn = null; + plBuilder = null; } TypeExpr te; try { - te = cn == null ? TypeExpr.ANYTHING : CastNodeSampler.createSampler(cn).resultTypes(); + if (plBuilder == null) { + te = TypeExpr.ANYTHING; + } else { + te = ResultTypesAnalyser.analyse(plBuilder.getFirstStep()).removeWildcards(); + + if (!te.and(rmissingType).isNothing()) { + // try to find a replacement for RMissing + if ((defParams != null && defParams.length > i) && defParams[i] != RMissing.instance) { + // Cancel RMissing in the result type if there is a + // substitution for it + te = te.and(rmissingType.not()); + } + } + + } } catch (Exception e) { throw new RuntimeException("Cannot create sampler for argument " + parameterNames[i], e); } @@ -361,6 +621,34 @@ public class RBuiltinDiagnostics { return typeName(m.getReturnType()) + " " + m.getName() + "(" + sb + ")"; } + private static Optional<Method> findFallbackMethod(Class<?> genBltnClass) { + Optional<Class<?>> fallbackNodeCls = Arrays.stream(genBltnClass.getDeclaredClasses()).filter(c -> "FallbackNode_".equals(c.getSimpleName())).findFirst(); + return fallbackNodeCls.flatMap(fc -> findFallbackMethodFromAnnot(fc, genBltnClass.getSuperclass())); + } + + private static Optional<Method> findFallbackMethodFromAnnot(Class<?> fallbackNodeClass, Class<?> bltnCls) { + GeneratedBy genByAnnot = fallbackNodeClass.getAnnotation(GeneratedBy.class); + assert genByAnnot != null; + String fallbackName = genByAnnot.methodName(); + + return findMethod(bltnCls, dm -> { + return dm.getAnnotation(Specialization.class) == null && fallbackName.startsWith(dm.getName() + "("); + }); + } + + private static Optional<Method> findMethod(Class<?> clazz, Predicate<Method> filter) { + Optional<Method> res = Arrays.asList(clazz.getDeclaredMethods()).stream().filter(filter).findFirst(); + if (res.isPresent()) { + return res; + } + + if (clazz.getSuperclass() != Object.class) { + return findMethod(clazz.getSuperclass(), filter); + } else { + return Optional.empty(); + } + } + public interface RBuiltinDiagFactory { String getBuiltinName(); @@ -368,8 +656,11 @@ public class RBuiltinDiagnostics { String[] getParameterNames(); - CastNode[] getCasts(); + Object[] getDefaultParameterValues(); + + CastNode[] getCastNodes(); + NodeWithArgumentCasts.Casts getCasts(); } public static final class RIntBuiltinDiagFactory implements RBuiltinDiagFactory { @@ -378,6 +669,11 @@ public class RBuiltinDiagnostics { public RIntBuiltinDiagFactory(RBuiltinFactory fact) { super(); + + if (!RBuiltinNode.class.isAssignableFrom(fact.getBuiltinNodeClass())) { + throw new InfoException("A 'fake' builtin"); + } + this.fact = fact; } @@ -403,9 +699,25 @@ public class RBuiltinDiagnostics { } @Override - public CastNode[] getCasts() { + public CastNode[] getCastNodes() { return fact.getConstructor().get().getCasts(); } + + @Override + public NodeWithArgumentCasts.Casts getCasts() { + return NodeWithArgumentCasts.Casts.getCasts(fact.getBuiltinNodeClass()); + } + + @Override + public Object[] getDefaultParameterValues() { + switch (getBuiltinKind()) { + case SUBSTITUTE: + case PRIMITIVE: + return fact.getConstructor().get().getDefaultParameterValues(); + default: + return null; + } + } } public static final class RExtBuiltinDiagFactory implements RBuiltinDiagFactory { @@ -422,18 +734,10 @@ public class RBuiltinDiagnostics { } @SuppressWarnings("unchecked") - public static RExtBuiltinDiagFactory create(String extBuiltinClsName) throws ClassNotFoundException { - Class<?> nodeClass = Class.forName(extBuiltinClsName); - - if (!Modifier.isFinal(nodeClass.getModifiers())) { - nodeClass = Class.forName(extBuiltinClsName + "NodeGen"); - if (!Modifier.isFinal(nodeClass.getModifiers())) { - throw new IllegalArgumentException("Invalid external builtin class name: " + extBuiltinClsName); - } - } + public static RExtBuiltinDiagFactory create(Class<?> nodeClass) { if (!RExternalBuiltinNode.class.isAssignableFrom(nodeClass)) { - throw new IllegalArgumentException(extBuiltinClsName + " is not a subclass of " + RExternalBuiltinNode.class.getName()); + throw new IllegalArgumentException(nodeClass.getName() + " is not a subclass of " + RExternalBuiltinNode.class.getName()); } Optional<Method> execMethod = Arrays.stream(nodeClass.getMethods()).filter( @@ -441,7 +745,7 @@ public class RBuiltinDiagnostics { if (execMethod.isPresent()) { return new RExtBuiltinDiagFactory((Class<RExternalBuiltinNode>) nodeClass, execMethod.get().getParameterCount()); } else { - throw new UnsupportedOperationException(extBuiltinClsName + " is not a supported external builtin class"); + throw new InfoException("no-args builtin '" + nodeClass.getName()); } } @@ -461,12 +765,36 @@ public class RBuiltinDiagnostics { } @Override - public CastNode[] getCasts() { + public CastNode[] getCastNodes() { try { return ((RExternalBuiltinNode) nodeClass.getMethod("create").invoke(null)).getCasts(); } catch (Exception e) { throw new RuntimeException(e); } } + + @Override + public NodeWithArgumentCasts.Casts getCasts() { + return NodeWithArgumentCasts.Casts.getCasts(getBuiltinNodeClass()); + } + + @Override + public Object[] getDefaultParameterValues() { + return null; + } + } + + @SuppressWarnings("serial") + private static final class InfoException extends RuntimeException { + InfoException(String msg) { + super(msg); + } + } + + @SuppressWarnings("serial") + private static final class WarningException extends RuntimeException { + WarningException(String msg) { + super(msg); + } } } diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java index 24af4e1560c7e5e6bea0d1cf987abc3a1b1ad702..ae709c5c8b51eb5655f9229e11cd69f35f90eb9b 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.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 @@ -32,6 +32,8 @@ import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RootWithBody; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.context.RContext.RCloseable; import com.oracle.truffle.r.runtime.data.RExpression; import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.env.REnvironment; @@ -259,6 +261,7 @@ public class SpecialCallTest extends TestBase { assertCallCounts("{}", test, initialSpecialCount, initialNormalCount, finalSpecialCount, finalNormalCount); } + @SuppressWarnings("try") private static void assertCallCounts(String setup, String test, int initialSpecialCount, int initialNormalCount, int finalSpecialCount, int finalNormalCount) { if (!FastROptions.UseSpecials.getBooleanValue()) { return; @@ -273,7 +276,7 @@ public class SpecialCallTest extends TestBase { RootCallTarget setupCallTarget = testVMContext.getThisEngine().makePromiseCallTarget(((RLanguage) setupExpression.getDataAt(0)).getRep().asRSyntaxNode().asRNode(), "test"); RootCallTarget testCallTarget = testVMContext.getThisEngine().makePromiseCallTarget(((RLanguage) testExpression.getDataAt(0)).getRep().asRSyntaxNode().asRNode(), "test"); - try { + try (RCloseable c = RContext.withinContext(TestBase.testVMContext)) { CountCallsVisitor count1 = new CountCallsVisitor(testCallTarget); Assert.assertEquals("initial special call count '" + setup + "; " + test + "': ", initialSpecialCount, count1.special); Assert.assertEquals("initial normal call count '" + setup + "; " + test + "': ", initialNormalCount, count1.normal); diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.java index 80bf53c93e4ed277799a2abe8485b1a1ca59694e..819cf8c85c13abb4ce3c2438edfd1ef9641e88d3 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.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 @@ -22,6 +22,8 @@ */ package com.oracle.truffle.r.nodes.test; +import java.util.function.Supplier; + import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; @@ -148,6 +150,21 @@ public class TestUtilities { return list; } + public static RAbstractVector copy(RAbstractVector orig) { + return withinTestContext(() -> orig.copy()); + } + + /** + * Certain code needs to be run within valid RContext, e.g. copying, which tries to report to + * memory tracer taken from RContext. + */ + @SuppressWarnings("try") + public static <T> T withinTestContext(Supplier<T> action) { + try (RCloseable c = RContext.withinContext(TestBase.testVMContext)) { + return action.get(); + } + } + /** * Creates a handle that emulates the behavior as if this node would be executed inside of an R * call. @@ -192,6 +209,7 @@ public class TestUtilities { private final NodeAdapter<T> invoke; @Child private T node; + @SuppressWarnings("deprecation") TestRoot(T node, NodeAdapter<T> invoke) { super(TruffleLanguage.class, null, null); this.node = node; diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/UnaryArithmeticNodeTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/UnaryArithmeticNodeTest.java index d729c5df6da3160301223a1c6fb97c2b15d4e60d..c575efa26a681a498bc5253cb5fe78ff1281aacc 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/UnaryArithmeticNodeTest.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/UnaryArithmeticNodeTest.java @@ -22,7 +22,9 @@ */ package com.oracle.truffle.r.nodes.test; +import static com.oracle.truffle.r.nodes.test.TestUtilities.copy; import static com.oracle.truffle.r.nodes.test.TestUtilities.createHandle; +import static com.oracle.truffle.r.nodes.test.TestUtilities.withinTestContext; import static com.oracle.truffle.r.runtime.data.RDataFactory.createDoubleSequence; import static com.oracle.truffle.r.runtime.data.RDataFactory.createIntSequence; import static com.oracle.truffle.r.runtime.ops.UnaryArithmetic.NEGATE; @@ -81,7 +83,7 @@ public class UnaryArithmeticNodeTest extends BinaryVectorTest { @Theory public void testVectorResult(UnaryArithmeticFactory factory, RAbstractVector originalOperand) { - RAbstractVector operand = originalOperand.copy(); + RAbstractVector operand = copy(originalOperand); assumeThat(operand, is(not(instanceOf(RScalarVector.class)))); Object result = executeArithmetic(factory, operand); @@ -94,7 +96,7 @@ public class UnaryArithmeticNodeTest extends BinaryVectorTest { @Theory public void testSharing(UnaryArithmeticFactory factory, RAbstractVector originalOperand) { - RAbstractVector operand = originalOperand.copy(); + RAbstractVector operand = copy(originalOperand); // sharing does not work if a is a scalar vector assumeThat(true, is(isShareable(operand, operand.getRType()))); @@ -128,7 +130,7 @@ public class UnaryArithmeticNodeTest extends BinaryVectorTest { @Theory public void testCompleteness(UnaryArithmeticFactory factory, RAbstractVector originalOperand) { - RAbstractVector operand = originalOperand.copy(); + RAbstractVector operand = copy(originalOperand); Object result = executeArithmetic(factory, operand); boolean resultComplete = isPrimitive(result) ? true : ((RAbstractVector) result).isComplete(); @@ -143,21 +145,21 @@ public class UnaryArithmeticNodeTest extends BinaryVectorTest { @Theory public void testCopyAttributes(UnaryArithmeticFactory factory, RAbstractVector originalOperand) { - RAbstractVector operand = originalOperand.copy(); + RAbstractVector operand = copy(originalOperand); // we have to e careful not to change mutable vectors - RAbstractVector a = operand.copy(); + RAbstractVector a = copy(operand); if (a instanceof RShareable) { ((RShareable) a).incRefCount(); } - RVector<?> aMaterialized = a.copy().materialize(); + RVector<?> aMaterialized = withinTestContext(() -> a.copy().materialize()); aMaterialized.setAttr("a", "a"); - assertAttributes(executeArithmetic(factory, aMaterialized.copy()), "a"); + assertAttributes(executeArithmetic(factory, copy(aMaterialized)), "a"); } @Theory public void testPlusFolding(RAbstractVector originalOperand) { - RAbstractVector operand = originalOperand.copy(); + RAbstractVector operand = copy(originalOperand); assumeThat(operand, is(not(instanceOf(RScalarVector.class)))); if (operand.getRType() == getArgumentType(operand)) { assertFold(true, operand, PLUS); @@ -178,7 +180,7 @@ public class UnaryArithmeticNodeTest extends BinaryVectorTest { public void testGeneric(UnaryArithmeticFactory factory) { // this should trigger the generic case for (RAbstractVector vector : ALL_VECTORS) { - executeArithmetic(factory, vector.copy()); + executeArithmetic(factory, copy(vector)); } } diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/BypassNodeGenSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/BypassNodeGenSampler.java deleted file mode 100644 index 8ec4b0dc84d206a7fd9d692a726ff9f595062842..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/BypassNodeGenSampler.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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.nodes.unary; - -import com.oracle.truffle.r.nodes.casts.ArgumentMapperSampler; -import com.oracle.truffle.r.nodes.casts.CastNodeSampler; -import com.oracle.truffle.r.nodes.casts.Samples; -import com.oracle.truffle.r.nodes.casts.TypeExpr; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RNull; - -@SuppressWarnings({"rawtypes", "unchecked"}) -public class BypassNodeGenSampler extends CastNodeSampler<BypassNodeGen> { - - private final CastNodeSampler wrappedHeadSampler; - private final ArgumentMapperSampler nullMapper; - private final ArgumentMapperSampler missingMapper; - - public BypassNodeGenSampler(BypassNodeGen bypassNode) { - super(bypassNode); - this.wrappedHeadSampler = bypassNode.getWrappedHead() == null ? null : createSampler(bypassNode.getWrappedHead()); - - assert bypassNode.getNullMapper() == null || bypassNode.getNullMapper() instanceof ArgumentMapperSampler; - assert bypassNode.getMissingMapper() == null || bypassNode.getMissingMapper() instanceof ArgumentMapperSampler; - - this.nullMapper = (ArgumentMapperSampler) bypassNode.getNullMapper(); - this.missingMapper = (ArgumentMapperSampler) bypassNode.getMissingMapper(); - } - - @Override - public TypeExpr resultTypes(TypeExpr inputTypes, SamplingContext ctx) { - TypeExpr rt = wrappedHeadSampler == null ? TypeExpr.ANYTHING : wrappedHeadSampler.resultTypes(inputTypes, ctx); - if (nullMapper != null) { - rt = rt.or(nullMapper.resultTypes(inputTypes)); - } else { - rt = rt.and(TypeExpr.atom(RNull.class).not()); - } - if (missingMapper != null) { - rt = rt.or(missingMapper.resultTypes(inputTypes)); - } else { - rt = rt.and(TypeExpr.atom(RMissing.class).not()); - } - return rt; - } - - @Override - public Samples<?> collectSamples(TypeExpr inputType, Samples<?> downStreamSamples) { - Samples<?> samples = wrappedHeadSampler == null ? Samples.nothing() : wrappedHeadSampler.collectSamples(inputType, downStreamSamples); - if (nullMapper != null) { - samples = samples.or(nullMapper.collectSamples(downStreamSamples)); - } - if (missingMapper != null) { - samples = samples.or(missingMapper.collectSamples(downStreamSamples)); - } - return samples; - } -} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/CastToVectorNodeGenSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/CastToVectorNodeGenSampler.java deleted file mode 100644 index c493163b6412d5c2bcb7906e72569d08de0ddf4e..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/CastToVectorNodeGenSampler.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 - * 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.unary; - -import java.util.Arrays; -import java.util.List; - -import com.oracle.truffle.r.nodes.casts.CastNodeSampler; -import com.oracle.truffle.r.nodes.casts.CastUtils.Cast; -import com.oracle.truffle.r.nodes.casts.CastUtils.Casts; -import com.oracle.truffle.r.nodes.casts.Samples; -import com.oracle.truffle.r.nodes.casts.TypeExpr; -import com.oracle.truffle.r.runtime.data.RExpression; -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.model.RAbstractVector; - -public class CastToVectorNodeGenSampler extends CastNodeSampler<CastToVectorNodeGen> { - - public CastToVectorNodeGenSampler(CastToVectorNodeGen castNode) { - super(castNode); - } - - @Override - public TypeExpr resultTypes(TypeExpr inputType, SamplingContext ctx) { - List<Cast> castList; - if (castNode.isPreserveNonVector()) { - castList = Arrays.asList(new Cast(RNull.class, RNull.class), - new Cast(RMissing.class, RNull.class), - new Cast(RFunction.class, RFunction.class), - new Cast(RAbstractVector.class, RAbstractVector.class), - new Cast(RExpression.class, RList.class)); - } else { - castList = Arrays.asList(new Cast(RNull.class, RList.class), - new Cast(RMissing.class, RList.class), - new Cast(RFunction.class, RList.class), - new Cast(RAbstractVector.class, RAbstractVector.class), - new Cast(RExpression.class, RList.class)); - } - TypeExpr narrowed = Casts.createCasts(castList).narrow(inputType); - return narrowed; - } - - @Override - public Samples<?> collectSamples(TypeExpr inputType, Samples<?> downStreamSamples) { - return downStreamSamples; - } -} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/ChainedCastNodeSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/ChainedCastNodeSampler.java deleted file mode 100644 index d2a01b173dac7a46cd17a6eb65c0c7561c0727a9..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/ChainedCastNodeSampler.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 - * 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.unary; - -import com.oracle.truffle.r.nodes.casts.CastNodeSampler; -import com.oracle.truffle.r.nodes.casts.Samples; -import com.oracle.truffle.r.nodes.casts.TypeExpr; - -public final class ChainedCastNodeSampler extends CastNodeSampler<ChainedCastNode> { - - private final CastNodeSampler<?> firstCast; - private final CastNodeSampler<?> secondCast; - - public ChainedCastNodeSampler(ChainedCastNode castNode) { - super(castNode); - - firstCast = createSampler(castNode.getFirstCast()); - secondCast = createSampler(castNode.getSecondCast()); - } - - @Override - public TypeExpr resultTypes(TypeExpr inputTypes, SamplingContext ctx) { - return secondCast.resultTypes(firstCast.resultTypes(inputTypes, ctx), ctx); - } - - @Override - public String toString() { - return firstCast.toString(); - } - - @Override - public Samples<?> collectSamples(TypeExpr inputTypes, Samples<?> downStreamSamples) { - TypeExpr rt1 = firstCast.resultTypes(inputTypes, new SamplingContext()); - return firstCast.collectSamples(inputTypes, secondCast.collectSamples(rt1, downStreamSamples)); - } -} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/ConditionalMapNodeGenSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/ConditionalMapNodeGenSampler.java deleted file mode 100644 index 3b8a88b0170a86fe063aae145449dcae7b0dc21a..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/ConditionalMapNodeGenSampler.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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 - * 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.unary; - -import com.oracle.truffle.r.nodes.casts.ArgumentFilterSampler; -import com.oracle.truffle.r.nodes.casts.CastNodeSampler; -import com.oracle.truffle.r.nodes.casts.Samples; -import com.oracle.truffle.r.nodes.casts.TypeExpr; - -@SuppressWarnings({"rawtypes", "unchecked"}) -public class ConditionalMapNodeGenSampler extends CastNodeSampler<ConditionalMapNodeGen> { - - private final ArgumentFilterSampler argFilter; - private final CastNodeSampler trueBranch; - private final CastNodeSampler falseBranch; - - public ConditionalMapNodeGenSampler(ConditionalMapNodeGen castNode) { - super(castNode); - argFilter = (ArgumentFilterSampler) castNode.getFilter(); - trueBranch = createSampler(castNode.getTrueBranch()); - falseBranch = createSampler(castNode.getFalseBranch()); - } - - @Override - public TypeExpr resultTypes(TypeExpr inputType, SamplingContext ctx) { - if (castNode.isReturns()) { - ctx.addAltResultType(trueBranchResultTypes(inputType, ctx)); - return falseBranchResultTypes(inputType, ctx); - } else { - return trueBranchResultTypes(inputType, ctx).or(falseBranchResultTypes(inputType, ctx)); - } - } - - private TypeExpr trueBranchResultTypes(TypeExpr inputType, SamplingContext ctx) { - if (trueBranch != null) { - return trueBranch.resultTypes(argFilter.trueBranchType().and(inputType), ctx); - } else { - return argFilter.trueBranchType().and(inputType); - } - } - - private TypeExpr falseBranchResultTypes(TypeExpr inputType, SamplingContext ctx) { - if (falseBranch != null) { - return falseBranch.resultTypes(argFilter.falseBranchType().and(inputType), ctx); - } else { - return argFilter.falseBranchType().and(inputType); - } - } - - @Override - public Samples<?> collectSamples(TypeExpr inputType, Samples<?> downStreamSamples) { - TypeExpr trueBranchResultType = trueBranchResultTypes(inputType, new SamplingContext()); - TypeExpr falseBranchResultType = falseBranchResultTypes(inputType, new SamplingContext()); - - // filter out the incompatible samples - Samples compatibleTrueBranchDownStreamSamples = downStreamSamples.filter(x -> trueBranchResultType.isInstance(x)); - Samples compatibleFalseBranchDownStreamSamples = downStreamSamples.filter(x -> falseBranchResultType.isInstance(x)); - - Samples trueBranchSamples = trueBranch.collectSamples(argFilter.trueBranchType().and(inputType), compatibleTrueBranchDownStreamSamples); - Samples falseBranchSamples = falseBranch == null ? compatibleFalseBranchDownStreamSamples - : falseBranch.collectSamples(argFilter.falseBranchType().and(inputType), compatibleFalseBranchDownStreamSamples); - Samples bothBranchesSamples = trueBranchSamples.or(falseBranchSamples); - - // Collect the "interesting" samples from the condition. Both positive and negative samples - // are actually interpreted as positive ones. - Samples origConditionSamples = argFilter.collectSamples(inputType).makePositive(); - // Merge the samples from the branches with the condition samples - return origConditionSamples.or(bothBranchesSamples); - } -} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FilterNodeGenSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FilterNodeGenSampler.java deleted file mode 100644 index 4a73a29cce796b9c4de37d7120fb19c116a28523..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FilterNodeGenSampler.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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 - * 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.unary; - -import com.oracle.truffle.r.nodes.casts.ArgumentFilterSampler; -import com.oracle.truffle.r.nodes.casts.CastNodeSampler; -import com.oracle.truffle.r.nodes.casts.Samples; -import com.oracle.truffle.r.nodes.casts.TypeExpr; - -@SuppressWarnings("rawtypes") -public class FilterNodeGenSampler extends CastNodeSampler<FilterNodeGen> { - - private final ArgumentFilterSampler filter; - private final boolean isWarning; - private final TypeExpr resType; - - public FilterNodeGenSampler(FilterNodeGen castNode) { - super(castNode); - assert castNode.getFilter() instanceof ArgumentFilterSampler : "Check PredefFiltersSamplers is installed in Predef"; - this.filter = (ArgumentFilterSampler) castNode.getFilter(); - this.isWarning = castNode.isWarning(); - this.resType = filter.trueBranchType(); - } - - @Override - public TypeExpr resultTypes(TypeExpr inputType, SamplingContext ctx) { - if (isWarning) { - return inputType; - } else { - return inputType.and(resType); - } - } - - @SuppressWarnings("unchecked") - @Override - public Samples<?> collectSamples(TypeExpr inputType, Samples<?> downStreamSamples) { - if (isWarning) { - return downStreamSamples; - } else { - Samples samples = filter.collectSamples(inputType); - - Samples<?> combined = samples.and(downStreamSamples); - return combined; - } - } -} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FindFirstNodeGenSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FindFirstNodeGenSampler.java deleted file mode 100644 index 2135903ab21d91d006f2b82824b22752ac89448c..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FindFirstNodeGenSampler.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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 - * 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.unary; - -import java.lang.reflect.Type; -import java.util.HashSet; -import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import com.oracle.truffle.r.nodes.casts.CastNodeSampler; -import com.oracle.truffle.r.nodes.casts.CastUtils; -import com.oracle.truffle.r.nodes.casts.Samples; -import com.oracle.truffle.r.nodes.casts.TypeExpr; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; - -public class FindFirstNodeGenSampler extends CastNodeSampler<FindFirstNodeGen> { - - private final Object defaultValue; - private final Class<?> elementClass; - - public FindFirstNodeGenSampler(FindFirstNodeGen castNode) { - super(castNode); - this.elementClass = castNode.getElementClass(); - this.defaultValue = castNode.getDefaultValue(); - } - - @Override - public Samples<?> collectSamples(TypeExpr inputType, Samples<?> downStreamSamples) { - Samples<Object> defaultSamples = defaultSamples(); - - // convert scalar samples to vector ones - Samples<Object> vectorizedSamples = downStreamSamples.map(x -> CastUtils.singletonVector(x), x -> CastUtils.singletonVector(x), - x -> CastUtils.firstElement(x, defaultValue), x -> CastUtils.firstElement(x, defaultValue)); - Samples<Object> combined = defaultSamples.and(vectorizedSamples); - return combined; - } - - private Samples<Object> defaultSamples() { - Set<Object> defaultNegativeSamples = new HashSet<>(); - Set<Object> defaultPositiveSamples = new HashSet<>(); - - if (defaultValue == null) { - defaultNegativeSamples.add(RNull.instance); - Object emptyVec = CastUtils.emptyVector(elementClass); - if (emptyVec != null) { - defaultNegativeSamples.add(emptyVec); - } - - Predicate<Object> posMembership = this::testVectorForNoDefaultValCase; - - return new Samples<>("findFirst-noDef", defaultPositiveSamples, defaultNegativeSamples, posMembership); - } else { - defaultPositiveSamples.add(CastUtils.singletonVector(defaultValue)); - defaultPositiveSamples.add(RNull.instance); - Object emptyVec = CastUtils.emptyVector(elementClass); - if (emptyVec != null) { - defaultPositiveSamples.add(emptyVec); - } - - Predicate<Object> posMembership = this::testVectorForDefaultValCase; - - return new Samples<>("findFirst-withDef", defaultPositiveSamples, defaultNegativeSamples, posMembership); - } - } - - private boolean testVectorForNoDefaultValCase(Object x) { - if (x == RMissing.instance || x == RNull.instance || x == null) { - return false; - } - - if (x instanceof RAbstractVector) { - Class<?> elemCls = CastUtils.vectorElementType(x).orElse(null); - return elemCls != null && elementClass.isAssignableFrom(elemCls) && ((RAbstractVector) x).getLength() > 0; - } else { - return elementClass.isInstance(x); - } - } - - private boolean testVectorForDefaultValCase(Object x) { - if (x == RMissing.instance || x == RNull.instance || x == null) { - return true; - } - - if (x instanceof RAbstractVector) { - Class<?> elemCls = CastUtils.vectorElementType(x).orElse(null); - return elemCls != null && elementClass.isAssignableFrom(elemCls); - } else { - return elementClass.isInstance(x); - } - } - - @Override - public TypeExpr resultTypes(TypeExpr inputType, SamplingContext ctx) { - TypeExpr rt; - if (elementClass == null || elementClass == Object.class) { - if (inputType.isAnything()) { - rt = TypeExpr.atom(RAbstractVector.class).not(); - } else { - Set<Type> resTypes = inputType.classify().stream().map(c -> CastUtils.elementType(c)).collect(Collectors.toSet()); - rt = TypeExpr.union(resTypes); - } - } else { - rt = TypeExpr.atom(elementClass); - } - - return rt; - } -} diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/NonNANodeGenSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/NonNANodeGenSampler.java deleted file mode 100644 index 3f2f805208270c2e745f75310873ffcb433ce6e9..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/NonNANodeGenSampler.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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 - * 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.unary; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Optional; -import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import com.oracle.truffle.r.nodes.casts.CastNodeSampler; -import com.oracle.truffle.r.nodes.casts.CastUtils; -import com.oracle.truffle.r.nodes.casts.Samples; -import com.oracle.truffle.r.nodes.casts.TypeExpr; - -public class NonNANodeGenSampler extends CastNodeSampler<NonNANodeGen> { - - private final Object naReplacement; - - public NonNANodeGenSampler(NonNANodeGen castNode) { - super(castNode); - naReplacement = castNode.getNAReplacement(); - } - - @Override - public TypeExpr resultTypes(TypeExpr inputType, SamplingContext ctx) { - return inputType; - } - - @SuppressWarnings("unchecked") - private <T> Optional<T> unmap(T x) { - if (naReplacement == null) { - return CastUtils.isNaValue(x) ? Optional.empty() : Optional.of(x); - } else { - return CastUtils.isNaValue(x) ? Optional.of((T) naReplacement) : Optional.of(x); - } - } - - @SuppressWarnings("unchecked") - @Override - public Samples<?> collectSamples(TypeExpr inputTypes, Samples<?> downStreamSamples) { - Set<Object> defaultPositiveSamples; - Set<Object> defaultNegativeSamples; - - Samples<Object> mappedSamples = ((Samples<Object>) downStreamSamples).map(x -> x, x -> x, this::unmap, this::unmap); - - Set<Object> naSamples = inputTypes.normalize().stream().filter(t -> t instanceof Class).map(t -> CastUtils.naValue((Class<?>) t)).filter(x -> x != null).collect(Collectors.toSet()); - if (naReplacement != null) { - defaultNegativeSamples = Collections.emptySet(); - defaultPositiveSamples = new HashSet<>(); - defaultPositiveSamples.add(naReplacement); - defaultPositiveSamples.addAll(naSamples); - } else { - defaultNegativeSamples = naSamples; - defaultPositiveSamples = Collections.emptySet(); - } - - Predicate<Object> posMembership = x -> naReplacement != null || !CastUtils.isNaValue(x); - Samples<Object> defaultSamples = new Samples<>("nonNA-" + naReplacement == null ? "noDef" : "withDef", defaultPositiveSamples, defaultNegativeSamples, posMembership); - - Samples<Object> combined = defaultSamples.and(mappedSamples); - return combined; - } -} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java index 929e53938623402ab75e0db4ae3dfa7b0ab7a697..f1ed9c18960d1dd7b7fdb932a1c27974c649d1b4 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.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 @@ -31,7 +31,6 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinFactory; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.FormalArguments; import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; -import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.HasSignature; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.builtins.FastPathFactory; @@ -46,16 +45,11 @@ public abstract class RRootNode extends RootNode implements HasSignature { private final ConditionProfile irregularFrameProfile = ConditionProfile.createBinaryProfile(); - /** - * The formal arguments this function is supposed to take. - */ - private final FormalArguments formalArguments; - private FastPathFactory fastPath; - protected RRootNode(FormalArguments formalArguments, FrameDescriptor frameDescriptor, FastPathFactory fastPath) { + @SuppressWarnings("deprecation") + protected RRootNode(FrameDescriptor frameDescriptor, FastPathFactory fastPath) { super(RContext.getRForeignAccessFactory().getTruffleLanguage(), RSyntaxNode.SOURCE_UNAVAILABLE, frameDescriptor); - this.formalArguments = formalArguments; this.fastPath = fastPath; } @@ -66,25 +60,6 @@ public abstract class RRootNode extends RootNode implements HasSignature { RArguments.setIsIrregular(vf, irregularFrameProfile.profile(RArguments.getIsIrregular(vf))); } - /** - * @return The number of parameters this functions expects - */ - public final int getParameterCount() { - return formalArguments.getSignature().getLength(); - } - - /** - * @return {@link #formalArguments} - */ - public final FormalArguments getFormalArguments() { - return formalArguments; - } - - @Override - public final ArgumentsSignature getSignature() { - return formalArguments.getSignature(); - } - public final FastPathFactory getFastPath() { return fastPath; } @@ -93,6 +68,8 @@ public abstract class RRootNode extends RootNode implements HasSignature { this.fastPath = fastPath; } + public abstract FormalArguments getFormalArguments(); + public abstract boolean needsSplitting(); public abstract boolean containsDispatch(); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java index 2a5d3799e858c13015f210bfb9ee92d2277f93db..d5d8e0ad914e3e3c63f99e54fdf451f147224c65 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java @@ -23,8 +23,8 @@ import com.oracle.truffle.r.nodes.attributes.InitAttributesNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetClassAttributeNode; import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen; +import com.oracle.truffle.r.nodes.function.ImplicitClassHierarchyNode; import com.oracle.truffle.r.nodes.unary.TypeofNode; -import com.oracle.truffle.r.nodes.unary.TypeofNodeGen; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; @@ -49,7 +49,6 @@ public abstract class AccessSlotNode extends RBaseNode { public abstract Object executeAccess(Object o, String name); @Child private ClassHierarchyNode classHierarchy; - @Child private TypeofNode typeofNode; private final BranchProfile noSlot = BranchProfile.create(); private final BranchProfile symbolValue = BranchProfile.create(); @@ -83,13 +82,10 @@ public abstract class AccessSlotNode extends RBaseNode { return RNull.instance; } + CompilerDirectives.transferToInterpreter(); RStringVector classAttr = getClassNode.getClassAttr(object); if (classAttr == null) { - if (typeofNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - typeofNode = insert(TypeofNodeGen.create()); - } - throw RError.error(this, RError.Message.SLOT_CANNOT_GET, name, typeofNode.execute(object).getName()); + throw RError.error(this, RError.Message.SLOT_CANNOT_GET, name, TypeofNode.getTypeof(object).getName()); } else { throw RError.error(this, RError.Message.SLOT_NONE, name, classAttr.getLength() == 0 ? RRuntime.STRING_NA : classAttr.getDataAt(0)); } @@ -140,7 +136,7 @@ public abstract class AccessSlotNode extends RBaseNode { @Cached("create()") GetClassAttributeNode getClassNode) { RStringVector classAttr = getClassNode.getClassAttr(object); if (classAttr == null) { - RStringVector implicitClassVec = object.getImplicitClass(); + RStringVector implicitClassVec = ImplicitClassHierarchyNode.getImplicitClass(object); assert implicitClassVec.getLength() > 0; throw RError.error(this, RError.Message.SLOT_BASIC_CLASS, name, implicitClassVec.getDataAt(0)); } else { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java index 24f773ecefd8797ac57073bf5f97e2ad202c743b..e699b28a722a88eee6ce7197b16fa856e64056bb 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java @@ -28,11 +28,14 @@ import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; import com.oracle.truffle.api.frame.FrameSlotTypeException; +import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.data.RShareable; +import com.oracle.truffle.r.runtime.env.frame.ActiveBinding; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.RNode; @NodeChild(value = "rhs", type = RNode.class) @@ -44,7 +47,7 @@ import com.oracle.truffle.r.runtime.nodes.RNode; */ abstract class BaseWriteVariableNode extends WriteVariableNode { - protected BaseWriteVariableNode(Object name) { + protected BaseWriteVariableNode(String name) { super(name); } @@ -115,7 +118,7 @@ abstract class BaseWriteVariableNode extends WriteVariableNode { private boolean isCurrentValue(Frame frame, FrameSlot frameSlot, Object value) { try { - return isObjectProfile.profile(frame.isObject(frameSlot)) && isCurrentProfile.profile(frame.getObject(frameSlot) == value); + return isObjectProfile.profile(frame.isObject(frameSlot)) && isCurrentProfile.profile(FrameSlotChangeMonitor.getObject(frameSlot, frame) == value); } catch (FrameSlotTypeException ex) { throw RInternalError.shouldNotReachHere(); } @@ -153,4 +156,30 @@ abstract class BaseWriteVariableNode extends WriteVariableNode { } return false; } + + /** + * Handles an assignment to an active binding. + * + * @param execFrame The frame to be used for executing the function associated with the symbol. + * @param lookupFrame The frame to lookup the symbol (must not be {@code null}). + * @param value The value to set. + * @param frameSlot The frame slot of the value. + * @param invalidateProfile The invalidation profile. + */ + protected static Object handleActiveBinding(VirtualFrame execFrame, Frame lookupFrame, Object value, FrameSlot frameSlot, BranchProfile invalidateProfile, + ConditionProfile isActiveBindingProfile) { + Object object; + try { + object = lookupFrame.getObject(frameSlot); + } catch (FrameSlotTypeException e) { + object = null; + } + + if (isActiveBindingProfile.profile(object != null && ActiveBinding.isActiveBinding(object))) { + return ((ActiveBinding) object).writeValue(value); + } else { + FrameSlotChangeMonitor.setObjectAndInvalidate(lookupFrame, frameSlot, value, false, invalidateProfile); + } + return value; + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java index 3190231267184bebaa457bba097ccd3cc5966963..c54c9f419a7de9cd3e6165f0fc9c817f1ff3fffe 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.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 @@ -22,12 +22,9 @@ */ package com.oracle.truffle.r.nodes.access; -import static com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.findOrAddFrameSlot; - import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.FrameSlot; @@ -38,11 +35,10 @@ import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.nodes.NodeInfo; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; -import com.oracle.truffle.r.runtime.data.RTypes; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.env.frame.RFrameSlot; import com.oracle.truffle.r.runtime.nodes.RBaseNode; -@TypeSystemReference(RTypes.class) public abstract class FrameSlotNode extends RBaseNode { public abstract boolean hasValue(Frame frame); @@ -61,19 +57,23 @@ public abstract class FrameSlotNode extends RBaseNode { return new UnresolvedFrameSlotNode(name, createIfAbsent); } - public static FrameSlotNode createTemp(Object name, boolean createIfAbsent) { - return new UnresolvedFrameSlotNode(name, createIfAbsent); - } - public static FrameSlotNode create(RFrameSlot slot, boolean createIfAbsent) { return new UnresolvedFrameSlotNode(slot, createIfAbsent); } - public static FrameSlotNode createInitialized(FrameDescriptor frameDescriptor, Object identifier, boolean createIfAbsent) { + public static FrameSlotNode createInitialized(FrameDescriptor frameDescriptor, RFrameSlot identifier, boolean createIfAbsent) { + return createInitializedInternal(frameDescriptor, identifier, createIfAbsent); + } + + private static FrameSlotNode createInitializedInternal(FrameDescriptor frameDescriptor, Object identifier, boolean createIfAbsent) { FrameSlotNode newNode; FrameSlot frameSlot; if (createIfAbsent) { - frameSlot = findOrAddFrameSlot(frameDescriptor, identifier, FrameSlotKind.Illegal); + if (identifier instanceof String) { + frameSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frameDescriptor, (String) identifier, FrameSlotKind.Illegal); + } else { + frameSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frameDescriptor, (RFrameSlot) identifier, FrameSlotKind.Illegal); + } } else { frameSlot = frameDescriptor.findFrameSlot(identifier); } @@ -115,7 +115,7 @@ public abstract class FrameSlotNode extends RBaseNode { private FrameSlotNode resolveFrameSlot(Frame frame) { CompilerDirectives.transferToInterpreterAndInvalidate(); FrameDescriptor frameDescriptor = frame.getFrameDescriptor(); - FrameSlotNode newNode = createInitialized(frameDescriptor, identifier, createIfAbsent); + FrameSlotNode newNode = createInitializedInternal(frameDescriptor, identifier, createIfAbsent); return replace(newNode); } } @@ -177,7 +177,8 @@ public abstract class FrameSlotNode extends RBaseNode { public boolean hasValue(Frame frame) { try { Frame typedFrame = frameTypeProfile.profile(frame); - return !isObjectProfile.profile(typedFrame.isObject(frameSlot)) || isNullProfile.profile(typedFrame.getObject(frameSlot) != null); + return !isObjectProfile.profile(typedFrame.isObject(frameSlot)) || + isNullProfile.profile(FrameSlotChangeMonitor.getObject(frameSlot, typedFrame) != null); } catch (FrameSlotTypeException e) { throw new IllegalStateException(); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.java index 3b81ac8dd520cf893191165f24f463bcbf1cbde1..cf54077f8007c105d3e5e82be81a73dd4720b9b1 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.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 @@ -23,7 +23,6 @@ package com.oracle.truffle.r.nodes.access; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode; @@ -51,8 +50,6 @@ public class ReadVariadicComponentNode extends RSourceSectionNode implements RSy private final int index; private final String name; - private final BranchProfile errorBranch = BranchProfile.create(); - public ReadVariadicComponentNode(SourceSection src, int index) { super(src); this.index = index; @@ -65,17 +62,14 @@ public class ReadVariadicComponentNode extends RSourceSectionNode implements RSy Object args = lookup.execute(frame); if (args == null) { - errorBranch.enter(); - throw RError.error(this, RError.Message.NO_DOT_DOT, index + 1); + throw error(RError.Message.NO_DOT_DOT, index + 1); } RArgsValuesAndNames argsValuesAndNames = (RArgsValuesAndNames) args; if (argsValuesAndNames.isEmpty()) { - errorBranch.enter(); - throw RError.error(this, RError.Message.NO_LIST_FOR_CDR); + throw error(RError.Message.NO_LIST_FOR_CDR); } if (argsValuesAndNames.getLength() <= index) { - errorBranch.enter(); - throw RError.error(this, RError.Message.DOT_DOT_SHORT, index + 1); + throw error(RError.Message.DOT_DOT_SHORT, index + 1); } Object ret = argsValuesAndNames.getArgument(index); return ret == null ? RMissing.instance : promiseHelper.checkEvaluate(frame, ret); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java index 3a66dc1427fa8880bbf7e228ca667b1631edbb14..de421491f537708d3c5aa7632cd4721bfa9e5482 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.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 @@ -65,7 +65,7 @@ public abstract class RemoveAndAnswerNode extends RNode { private RemoveAndAnswerNode specialize(FrameSlot fs) { if (fs == null) { - RError.warning(RError.SHOW_CALLER, RError.Message.UNKNOWN_OBJECT, name); + warning(RError.Message.UNKNOWN_OBJECT, name); } return replace(RemoveAndAnswerResolvedNodeGen.create(fs)); } @@ -104,7 +104,7 @@ public abstract class RemoveAndAnswerNode extends RNode { protected Object doObject(VirtualFrame frame) { Object result; try { - result = frame.getObject(slot); + result = FrameSlotChangeMonitor.getObject(slot, frame); } catch (FrameSlotTypeException e) { throw RInternalError.shouldNotReachHere(); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateSlotNode.java index 4cd1ffa866ada9f3ed5cb3396c0ca55b103a22d6..59d8ab2c49c12060a5c96d63205779293f1f01e2 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateSlotNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateSlotNode.java @@ -15,7 +15,6 @@ package com.oracle.truffle.r.nodes.access; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.r.nodes.RASTUtils; import com.oracle.truffle.r.nodes.attributes.InitAttributesNode; import com.oracle.truffle.r.nodes.attributes.SetAttributeNode; import com.oracle.truffle.r.runtime.RCaller; @@ -32,6 +31,8 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; public abstract class UpdateSlotNode extends RBaseNode { + private static final String SET_DATA_PART = "setDataPart"; + public abstract Object executeUpdate(Object object, String name, Object value); protected SetAttributeNode createAttrUpdate() { @@ -56,12 +57,9 @@ public abstract class UpdateSlotNode extends RBaseNode { protected Object updateSlotS4Data(RAttributable object, @SuppressWarnings("unused") String name, Object value) { // TODO: any way to cache it or use a mechanism similar to overrides? REnvironment methodsNamespace = REnvironment.getRegisteredNamespace("methods"); - String identifier = "setDataPart"; - Object f = methodsNamespace.findFunction(identifier); - RFunction dataPart = (RFunction) RContext.getRRuntimeASTAccess().forcePromise(identifier, f); - return RContext.getEngine().evalFunction(dataPart, methodsNamespace.getFrame(), RCaller.create(null, RASTUtils.getOriginalCall(this)), null, object, - prepareValue(value), - RRuntime.LOGICAL_TRUE); + Object f = methodsNamespace.findFunction(SET_DATA_PART); + RFunction dataPart = (RFunction) RContext.getRRuntimeASTAccess().forcePromise(SET_DATA_PART, f); + return RContext.getEngine().evalFunction(dataPart, methodsNamespace.getFrame(), RCaller.createInvalid(null), null, object, prepareValue(value), RRuntime.LOGICAL_TRUE); } protected boolean isData(String name) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java index 8823779fd2583117c0daf220eaaf3c6dbacba15b..86d28f126c57d23da16604efa3726315ee20d2fd 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java @@ -22,6 +22,9 @@ */ package com.oracle.truffle.r.nodes.access; +import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; @@ -29,6 +32,7 @@ import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.RNode; @@ -41,11 +45,11 @@ import com.oracle.truffle.r.runtime.nodes.RNode; @ImportStatic(FrameSlotKind.class) public abstract class WriteLocalFrameVariableNode extends BaseWriteVariableNode { - public static WriteLocalFrameVariableNode create(Object name, Mode mode, RNode rhs) { + public static WriteLocalFrameVariableNode create(String name, Mode mode, RNode rhs) { return WriteLocalFrameVariableNodeGen.create(name, mode, rhs); } - public static WriteLocalFrameVariableNode createForRefCount(Object name) { + public static WriteLocalFrameVariableNode createForRefCount(String name) { return WriteLocalFrameVariableNodeGen.create(name, Mode.INVISIBLE, null); } @@ -53,8 +57,10 @@ public abstract class WriteLocalFrameVariableNode extends BaseWriteVariableNode private final ValueProfile storedObjectProfile = ValueProfile.createClassProfile(); private final BranchProfile invalidateProfile = BranchProfile.create(); + private final ConditionProfile isActiveBindingProfile = ConditionProfile.createBinaryProfile(); + @CompilationFinal private Assumption containsNoActiveBinding; - protected WriteLocalFrameVariableNode(Object name, Mode mode) { + protected WriteLocalFrameVariableNode(String name, Mode mode) { super(name); this.mode = mode; } @@ -87,8 +93,17 @@ public abstract class WriteLocalFrameVariableNode extends BaseWriteVariableNode @Specialization protected Object doObject(VirtualFrame frame, Object value, @Cached("findOrAddFrameSlot(frame, Object)") FrameSlot frameSlot) { - Object newValue = shareObjectValue(frame, frameSlot, storedObjectProfile.profile(value), mode, false); - FrameSlotChangeMonitor.setObjectAndInvalidate(frame, frameSlot, newValue, false, invalidateProfile); + if (containsNoActiveBinding == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + containsNoActiveBinding = FrameSlotChangeMonitor.getContainsNoActiveBindingAssumption(frame.getFrameDescriptor()); + } + if (containsNoActiveBinding.isValid()) { + Object newValue = shareObjectValue(frame, frameSlot, storedObjectProfile.profile(value), mode, false); + FrameSlotChangeMonitor.setObjectAndInvalidate(frame, frameSlot, newValue, false, invalidateProfile); + } else { + // it's a local variable lookup; so use 'frame' for both, executing and looking up + return handleActiveBinding(frame, frame, value, frameSlot, invalidateProfile, isActiveBindingProfile); + } return value; } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java index 8d5de24ba4a73eccd47637e876f98e21dbec25e5..a389e83a421b23979dea86644709a63e9e5aa1a1 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java @@ -24,7 +24,9 @@ package com.oracle.truffle.r.nodes.access; import static com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.findOrAddFrameSlot; +import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.FrameSlot; @@ -47,7 +49,7 @@ import com.oracle.truffle.r.runtime.nodes.RNode; */ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode { - protected WriteSuperFrameVariableNode(Object name) { + protected WriteSuperFrameVariableNode(String name) { super(name); } @@ -71,10 +73,12 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode { private final ValueProfile storedObjectProfile = ValueProfile.createClassProfile(); private final BranchProfile invalidateProfile = BranchProfile.create(); private final ValueProfile enclosingFrameProfile = ValueProfile.createClassProfile(); + private final ConditionProfile isActiveBindingProfile = ConditionProfile.createBinaryProfile(); private final Mode mode; + @CompilationFinal private Assumption containsNoActiveBinding; - public ResolvedWriteSuperFrameVariableNode(Object name, Mode mode) { + public ResolvedWriteSuperFrameVariableNode(String name, Mode mode) { super(name); this.mode = mode; } @@ -97,10 +101,18 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode { } @Specialization - protected void doObject(Object value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) { + protected void doObject(VirtualFrame frame, Object value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) { MaterializedFrame profiledFrame = enclosingFrameProfile.profile(enclosingFrame); - Object newValue = shareObjectValue(profiledFrame, frameSlot, storedObjectProfile.profile(value), mode, true); - FrameSlotChangeMonitor.setObjectAndInvalidate(profiledFrame, frameSlot, newValue, true, invalidateProfile); + if (containsNoActiveBinding == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + containsNoActiveBinding = FrameSlotChangeMonitor.getContainsNoActiveBindingAssumption(profiledFrame.getFrameDescriptor()); + } + if (containsNoActiveBinding != null && containsNoActiveBinding.isValid()) { + Object newValue = shareObjectValue(profiledFrame, frameSlot, storedObjectProfile.profile(value), mode, true); + FrameSlotChangeMonitor.setObjectAndInvalidate(profiledFrame, frameSlot, newValue, true, invalidateProfile); + } else { + handleActiveBinding(frame, profiledFrame, value, frameSlot, invalidateProfile, isActiveBindingProfile); + } } } @@ -110,7 +122,7 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode { private final Mode mode; - UnresolvedWriteSuperFrameVariableNode(Object name, Mode mode, RNode rhs) { + UnresolvedWriteSuperFrameVariableNode(String name, Mode mode, RNode rhs) { super(name); this.mode = mode; this.rhs = rhs; @@ -134,7 +146,7 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode { writeNode = ResolvedWriteSuperFrameVariableNodeGen.create(getName(), mode, rhs, enclosingFrameNode, FrameSlotNode.create(findOrAddFrameSlot(enclosingFrame.getFrameDescriptor(), getName(), FrameSlotKind.Illegal))); } else { - ResolvedWriteSuperFrameVariableNode actualWriteNode = ResolvedWriteSuperFrameVariableNodeGen.create(getName(), mode, null, null, FrameSlotNode.createTemp(getName(), false)); + ResolvedWriteSuperFrameVariableNode actualWriteNode = ResolvedWriteSuperFrameVariableNodeGen.create(getName(), mode, null, null, FrameSlotNode.create(getName(), false)); writeNode = new WriteSuperFrameVariableConditionalNode(getName(), actualWriteNode, new UnresolvedWriteSuperFrameVariableNode(getName(), mode, null), rhs); } replace(writeNode).execute(frame, value, enclosingFrame); @@ -163,7 +175,7 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode { private final ConditionProfile hasValueProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile nullSuperFrameProfile = ConditionProfile.createBinaryProfile(); - WriteSuperFrameVariableConditionalNode(Object name, ResolvedWriteSuperFrameVariableNode writeNode, WriteSuperFrameVariableNode nextNode, RNode rhs) { + WriteSuperFrameVariableConditionalNode(String name, ResolvedWriteSuperFrameVariableNode writeNode, WriteSuperFrameVariableNode nextNode, RNode rhs) { super(name); this.writeNode = writeNode; this.nextNode = nextNode; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.java index 9416b60d27eb77218c865980578d564b9467816f..2490221a608110e962270bc69ebbabbdaefc7797 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.java @@ -43,13 +43,13 @@ public abstract class WriteVariableNode extends RNode { INVISIBLE } - private final Object name; + private final String name; - protected WriteVariableNode(Object name) { + protected WriteVariableNode(String name) { this.name = name; } - public final Object getName() { + public final String getName() { return name; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java index 90211045dfd4bb77b50d240525f2413892dc7423..4ce17a2cce609f80633704791c90461355b68150 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.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 @@ -37,6 +37,8 @@ import com.oracle.truffle.r.nodes.function.PromiseHelperNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RPromise; +import com.oracle.truffle.r.runtime.env.frame.ActiveBinding; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; public final class LocalReadVariableNode extends Node { @@ -53,6 +55,7 @@ public final class LocalReadVariableNode extends Node { @CompilationFinal private FrameSlot frameSlot; @CompilationFinal private Assumption notInFrame; + @CompilationFinal private Assumption containsNoActiveBindingAssumption; private final ValueProfile frameProfile = ValueProfile.createClassProfile(); @@ -98,6 +101,7 @@ public final class LocalReadVariableNode extends Node { } Object result = null; if (isMissingProfile == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); seenValueKinds = new boolean[FrameSlotKind.values().length]; valueProfile = ValueProfile.createClassProfile(); isNullProfile = ConditionProfile.createBinaryProfile(); @@ -107,6 +111,16 @@ public final class LocalReadVariableNode extends Node { if (isNullProfile.profile(result == null) || isMissingProfile.profile(result == RMissing.instance)) { return null; } + + if (containsNoActiveBindingAssumption == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + containsNoActiveBindingAssumption = FrameSlotChangeMonitor.getContainsNoActiveBindingAssumption(profiledVariableFrame.getFrameDescriptor()); + } + // special treatment for active binding: call bound function + if (!containsNoActiveBindingAssumption.isValid() && ActiveBinding.isActiveBinding(result)) { + return ((ActiveBinding) result).readValue(); + } + if (forceResult) { if (isPromiseProfile == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java index 990fdbfe45be1c4e6996ccfc478b4d4a008d3c6b..5df1356f04147c5cae76348b71b5d1212b09636f 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java @@ -63,16 +63,18 @@ 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.RTypedValue; -import com.oracle.truffle.r.runtime.data.RTypesFlatLayout; +import com.oracle.truffle.r.runtime.data.RTypes; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; 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.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.env.frame.ActiveBinding; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.FrameAndSlotLookupResult; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.LookupResult; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.MultiSlotData; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; @@ -131,6 +133,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta @CompilationFinal private boolean needsCopying; private final ConditionProfile isPromiseProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile isActiveBindingProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile copyProfile; private final BranchProfile unexpectedMissingProfile = BranchProfile.create(); private final ValueProfile superEnclosingFrameProfile = ValueProfile.createClassProfile(); @@ -230,6 +233,9 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta } result = promiseHelper.evaluate(frame, (RPromise) result); } + if (isActiveBindingProfile.profile(ActiveBinding.isActiveBinding(result))) { + return ((ActiveBinding) result).readValue(); + } return result; } @@ -461,7 +467,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta } } if (frameSlot != null) { - Object value = variableFrame.getValue(frameSlot); + Object value = FrameSlotChangeMonitor.getObject(frameSlot, variableFrame); if (checkType(frame, value, isNullProfile)) { return value; } @@ -485,7 +491,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta @TruffleBoundary private Object getValue(MaterializedFrame current) { FrameSlot slot = current.getFrameDescriptor().findFrameSlot(identifier); - return slot == null ? null : current.getValue(slot); + return slot == null ? null : FrameSlotChangeMonitor.getValue(slot, current); } @Override @@ -565,8 +571,16 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta */ FrameSlot localSlot = variableFrame.getFrameDescriptor().findFrameSlot(identifier); // non-local reads can only be handled in a simple way if they are successful - if (localSlot != null && checkTypeSlowPath(frame, getValue(seenValueKinds, variableFrame, localSlot))) { - return new Match(localSlot); + if (localSlot != null) { + Object val = getValue(seenValueKinds, variableFrame, localSlot); + if (checkTypeSlowPath(frame, val)) { + if (val instanceof MultiSlotData) { + RError.performanceWarning("polymorphic (slow path) lookup of symbol \"" + identifier + "\" from a multi slot"); + return new Polymorphic(variableFrame); + } else { + return new Match(localSlot); + } + } } /* @@ -695,7 +709,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta // see if the current frame has a value of the given name FrameSlot frameSlot = current.getFrameDescriptor().findFrameSlot(identifier); if (frameSlot != null) { - Object value = current.getValue(frameSlot); + Object value = FrameSlotChangeMonitor.getValue(frameSlot, current); if (value != null) { if (value == RMissing.instance) { @@ -734,7 +748,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta // see if the current frame has a value of the given name FrameSlot frameSlot = current.getFrameDescriptor().findFrameSlot(identifier); if (frameSlot != null) { - Object value = current.getValue(frameSlot); + Object value = FrameSlotChangeMonitor.getValue(frameSlot, current); if (value != null) { if (value == RMissing.instance) { @@ -761,7 +775,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta // see if the current frame has a value of the given name FrameSlot frameSlot = current.getFrameDescriptor().findFrameSlot(ArgumentsSignature.VARARG_NAME); if (frameSlot != null) { - Object value = current.getValue(frameSlot); + Object value = FrameSlotChangeMonitor.getValue(frameSlot, current); if (value != null) { if (value == RNull.instance) { @@ -782,6 +796,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta assert variableFrame.getFrameDescriptor() == frameSlot.getFrameDescriptor(); Object value = variableFrame.getValue(frameSlot); if (variableFrame.isObject(frameSlot)) { + value = FrameSlotChangeMonitor.getValue(frameSlot, variableFrame); seenValueKinds[FrameSlotKind.Object.ordinal()] = true; } else if (variableFrame.isByte(frameSlot)) { seenValueKinds[FrameSlotKind.Byte.ordinal()] = true; @@ -797,7 +812,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta assert variableFrame.getFrameDescriptor() == frameSlot.getFrameDescriptor(); try { if (seenValueKinds[FrameSlotKind.Object.ordinal()] && variableFrame.isObject(frameSlot)) { - return variableFrame.getObject(frameSlot); + return FrameSlotChangeMonitor.getObject(frameSlot, variableFrame); } else if (seenValueKinds[FrameSlotKind.Byte.ordinal()] && variableFrame.isByte(frameSlot)) { return variableFrame.getByte(frameSlot); } else if (seenValueKinds[FrameSlotKind.Int.ordinal()] && variableFrame.isInt(frameSlot)) { @@ -930,7 +945,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta /* * This is RRuntime.checkType in the node form. */ -@TypeSystemReference(RTypesFlatLayout.class) +@TypeSystemReference(RTypes.class) abstract class CheckTypeNode extends RBaseNode { public abstract boolean executeBoolean(Object o); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java index a1447c00d9c472a11467a1a0189abf7c88da08ba..6a51aee479340ec59fb5b49bf3c6818c11f65971 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java @@ -192,7 +192,7 @@ final class CachedExtractVectorNode extends CachedVectorNode { if (oneDimensionProfile.profile(numberOfDimensions == 1)) { // names only need to be considered for single dimensional accesses if (getNamesNode == null) { - CompilerDirectives.transferToInterpreter(); + CompilerDirectives.transferToInterpreterAndInvalidate(); getNamesNode = insert(GetNamesAttributeNode.create()); } RStringVector originalNames = getNamesNode.getNames(vector); @@ -248,8 +248,7 @@ final class CachedExtractVectorNode extends CachedVectorNode { private Object doEnvironment(REnvironment env, Object[] positions) { if (mode.isSubset()) { - errorBranch.enter(); - throw RError.error(this, RError.Message.OBJECT_NOT_SUBSETTABLE, RType.Environment.getName()); + throw error(RError.Message.OBJECT_NOT_SUBSETTABLE, RType.Environment.getName()); } String positionString = tryCastSingleString(positionsCheckNode, positions); @@ -257,8 +256,7 @@ final class CachedExtractVectorNode extends CachedVectorNode { Object obj = env.get(positionString); return obj == null ? RNull.instance : obj; } - errorBranch.enter(); - throw RError.error(this, RError.Message.WRONG_ARGS_SUBSET_ENV); + throw error(RError.Message.WRONG_ARGS_SUBSET_ENV); } private boolean isMissingSingleDimension() { @@ -331,7 +329,7 @@ final class CachedExtractVectorNode extends CachedVectorNode { } else if (positionsCheckNode.isEmptyPosition(i, positions[i])) { result = RNull.instance; } else { - result = extract(i, (RAbstractStringVector) dataAt, positions[i], positionProfile[i]); + result = extract(i, (RAbstractStringVector) RRuntime.asAbstractVector(dataAt), positions[i], positionProfile[i]); } newDimNames[dimIndex] = result; if (newDimNamesNames != null) { @@ -468,7 +466,7 @@ final class CachedExtractVectorNode extends CachedVectorNode { protected void setNames(RVector<?> container, RAbstractStringVector newNames) { RStringVector newNames1 = newNames.materialize(); assert newNames1.getLength() <= container.getLength(); - assert container.getInternalDimensions() == null; + assert container.getAttr(RRuntime.DIM_ATTR_KEY) == null; if (container.getAttributes() == null) { // usual case container.initAttributes(RAttributesLayout.createNames(newNames1)); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java index 6e7fff3d2d83c7fd85d9fbb98b08e68f554be945..d6c7237c94a74eda98afe7663f56b53645e57c47 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java @@ -81,7 +81,6 @@ final class CachedReplaceVectorNode extends CachedVectorNode { private final BranchProfile warningBranch = BranchProfile.create(); private final ConditionProfile valueIsNA = ConditionProfile.createBinaryProfile(); private final BranchProfile resizeProfile = BranchProfile.create(); - private final BranchProfile sharedProfile = BranchProfile.create(); private final ConditionProfile rlanguageAttributesProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile valueLengthOneProfile = ConditionProfile.createBinaryProfile(); @@ -219,7 +218,7 @@ final class CachedReplaceVectorNode extends CachedVectorNode { PositionProfile[] positionProfiles = positionsCheckNode.executeCheck(vector, vectorDimensions, vectorLength, positions); if (castVectorNode != null) { - vector = (RAbstractVector) castVectorNode.execute(vector); + vector = (RAbstractVector) castVectorNode.doCast(vector); } int replacementLength = positionsCheckNode.getSelectedPositionsCount(positionProfiles); @@ -275,11 +274,10 @@ final class CachedReplaceVectorNode extends CachedVectorNode { */ if ((this.numberOfDimensions > 1 && isNullValue()) || (replacementLength != valueLength && replacementLength % valueLength != 0)) { if (this.numberOfDimensions > 1) { - errorBranch.enter(); - throw RError.error(this, RError.Message.NOT_MULTIPLE_REPLACEMENT); + throw error(RError.Message.NOT_MULTIPLE_REPLACEMENT); } else { warningBranch.enter(); - RError.warning(this, RError.Message.NOT_MULTIPLE_REPLACEMENT); + warning(RError.Message.NOT_MULTIPLE_REPLACEMENT); } } } @@ -410,24 +408,21 @@ final class CachedReplaceVectorNode extends CachedVectorNode { private void verifyValueLength(PositionProfile[] positionProfiles, int valueLength) { if (mode.isSubscript()) { if (!isList()) { - errorBranch.enter(); if (isNullValue()) { - throw RError.error(this, RError.Message.MORE_SUPPLIED_REPLACE); + throw error(RError.Message.MORE_SUPPLIED_REPLACE); } else if (valueLength == 0) { - throw RError.error(this, RError.Message.REPLACEMENT_0); + throw error(RError.Message.REPLACEMENT_0); } else { - throw RError.error(this, RError.Message.MORE_SUPPLIED_REPLACE); + throw error(RError.Message.MORE_SUPPLIED_REPLACE); } } } else { assert mode.isSubset(); if (!isNullValue() || this.numberOfDimensions == 1) { if (valueLength == 0) { - errorBranch.enter(); - throw RError.error(this, RError.Message.REPLACEMENT_0); + throw error(RError.Message.REPLACEMENT_0); } else if (positionsCheckNode.getContainsNA(positionProfiles)) { - errorBranch.enter(); - throw RError.error(this, RError.Message.NA_SUBSCRIPTED); + throw error(RError.Message.NA_SUBSCRIPTED); } } } @@ -461,14 +456,12 @@ final class CachedReplaceVectorNode extends CachedVectorNode { private Object doEnvironment(REnvironment env, Object[] positions, Object originalValues) { if (mode.isSubset()) { - errorBranch.enter(); - throw RError.error(this, RError.Message.OBJECT_NOT_SUBSETTABLE, RType.Environment.getName()); + throw error(RError.Message.OBJECT_NOT_SUBSETTABLE, RType.Environment.getName()); } String positionString = tryCastSingleString(positionsCheckNode, positions); if (positionString == null) { - errorBranch.enter(); - throw RError.error(this, RError.Message.WRONG_ARGS_SUBSET_ENV); + throw error(RError.Message.WRONG_ARGS_SUBSET_ENV); } try { @@ -515,8 +508,7 @@ final class CachedReplaceVectorNode extends CachedVectorNode { if (returnVector instanceof RShareable) { RShareable shareable = (RShareable) returnVector; // TODO find out if we need to copy always in the recursive case - if (sharedConditionProfile.execute(shareable.isShared()) || recursive || valueEqualsVectorProfile.profile(vector == value)) { - sharedProfile.enter(); + if (recursive || sharedConditionProfile.execute(shareable.isShared()) || valueEqualsVectorProfile.profile(vector == value)) { shareable = (RShareable) returnVector.copy(); returnVector = (RAbstractVector) shareable; assert shareable.isTemporary(); @@ -529,7 +521,7 @@ final class CachedReplaceVectorNode extends CachedVectorNode { return returnVector; } - // TODO (chumer) this is way to compilicated at the moment + // TODO (chumer) this is way to complicated at the moment // not yet worth compiling. we should introduce some nodes for this @TruffleBoundary private static void copyAttributes(RAbstractVector vector, RList result) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedVectorNode.java index ddd61957c7c5e09b7df428161eff08cd00e3ace4..bc1808ef44f397cffccff97f64d796d2dfa87c38 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedVectorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedVectorNode.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 @@ -23,7 +23,6 @@ package com.oracle.truffle.r.nodes.access.vector; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; @@ -54,7 +53,6 @@ abstract class CachedVectorNode extends RBaseNode { */ protected final boolean recursive; - protected final BranchProfile errorBranch = BranchProfile.create(); protected final int numberOfDimensions; private final int filteredPositionsLength; @@ -75,7 +73,7 @@ abstract class CachedVectorNode extends RBaseNode { } if (!isSubsetable(vectorType)) { error = () -> { - throw RError.error(this, RError.Message.OBJECT_NOT_SUBSETTABLE, vectorType.getName()); + throw error(RError.Message.OBJECT_NOT_SUBSETTABLE, vectorType.getName()); }; } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractListElement.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractListElement.java index 485ca001bcc8c4dc4266b01c4640968f12a74d5e..4890e66223c17dbf8ec4d68269cccce60106173c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractListElement.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractListElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,9 +24,7 @@ package com.oracle.truffle.r.nodes.access.vector; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.nodes.function.opt.UpdateShareableChildValueNode; import com.oracle.truffle.r.runtime.data.RListBase; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; @@ -47,7 +45,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; * convenient wrapper that performs the extraction as well as invocation of * {@link UpdateShareableChildValueNode}. See also the documentation of {@link RListBase}. */ -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) public abstract class ExtractListElement extends Node { public abstract Object execute(RAbstractContainer container, int index); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java index 44e7a6d2dfe803a82918c3f29d4ee2cdf9549a02..0cf2cec1a7b4ff575a71ba46cabadb79aff66f8e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java @@ -23,14 +23,20 @@ package com.oracle.truffle.r.nodes.access.vector; import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.InteropException; +import com.oracle.truffle.api.interop.KeyInfo; 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.java.JavaInterop; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode; @@ -41,6 +47,7 @@ import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RLogical; import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @@ -48,6 +55,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +@ImportStatic({RRuntime.class, com.oracle.truffle.api.interop.Message.class}) public abstract class ExtractVectorNode extends Node { protected static final int CACHE_LIMIT = 5; @@ -88,51 +96,90 @@ public abstract class ExtractVectorNode extends Node { protected abstract Object execute(VirtualFrame frame, Object vector, Object[] positions, Object exact, Object dropDimensions); - protected Node createForeignRead(Object[] positions) { - if (positions.length != 1) { - throw RError.error(this, RError.Message.GENERIC, "Invalid number positions for foreign access."); - } - return Message.READ.createNode(); - } - protected static boolean isForeignObject(TruffleObject object) { return RRuntime.isForeignObject(object); } protected static FirstStringNode createFirstString() { - return FirstStringNode.createWithError(RError.Message.GENERIC, "Cannot corce position to character for foreign access."); + return FirstStringNode.createWithError(RError.Message.GENERIC, "Cannot coerce position to character for foreign access."); } @Specialization(guards = {"isForeignObject(object)", "positions.length == cachedLength"}) protected Object accessField(TruffleObject object, Object[] positions, @SuppressWarnings("unused") Object exact, @SuppressWarnings("unused") Object dropDimensions, - @Cached("createForeignRead(positions)") Node foreignRead, + @Cached("READ.createNode()") Node foreignRead, + @Cached("KEY_INFO.createNode()") Node keyInfoNode, @Cached("positions.length") @SuppressWarnings("unused") int cachedLength, @Cached("create()") CastStringNode castNode, @Cached("createFirstString()") FirstStringNode firstString, - @Cached("createClassProfile()") ValueProfile positionProfile) { - Object position = positionProfile.profile(positions[0]); + @Cached("createClassProfile()") ValueProfile positionProfile, + @Cached("IS_NULL.createNode()") Node isNullNode, + @Cached("IS_BOXED.createNode()") Node isBoxedNode, + @Cached("UNBOX.createNode()") Node unboxNode) { + if (positions.length == 0) { + throw RError.error(this, RError.Message.GENERIC, "No positions for foreign access."); + } + positions = positionProfile.profile(positions); try { - if (position instanceof Integer) { - return ForeignAccess.send(foreignRead, object, new Object[]{((int) position) - 1}); - } else if (position instanceof Double) { - return ForeignAccess.send(foreignRead, object, new Object[]{((double) position) - 1}); - } else if (position instanceof String) { - return ForeignAccess.send(foreignRead, object, new Object[]{position}); - } else if (position instanceof RAbstractStringVector) { - String string = firstString.executeString(castNode.execute(position)); - return ForeignAccess.send(foreignRead, object, new Object[]{string}); - } else if (position instanceof RAbstractDoubleVector) { - return ForeignAccess.send(foreignRead, object, new Object[]{((RAbstractDoubleVector) position).getDataAt(0) - 1}); - } else if (position instanceof RAbstractIntVector) { - return ForeignAccess.send(foreignRead, object, new Object[]{((RAbstractIntVector) position).getDataAt(0) - 1}); - } else { - throw RError.error(this, RError.Message.GENERIC, "invalid index during foreign access"); + try { + // TODO implicite unboxing ok? method calls seem to behave this way + Object result = object; + for (int i = 0; i < positions.length; i++) { + result = read(this, positions[i], foreignRead, keyInfoNode, (TruffleObject) result, firstString, castNode); + if (positions.length > 1 && i < positions.length - 1) { + assert result instanceof TruffleObject; + } + } + return unbox(result, isNullNode, isBoxedNode, unboxNode); + } catch (UnknownIdentifierException | NoSuchFieldError e) { + throw RError.interopError(RError.findParentRBase(this), e, object); } } catch (InteropException e) { throw RError.interopError(RError.findParentRBase(this), e, object); } } + private Object unbox(Object obj, Node isNullNode, Node isBoxedNode, Node unboxNode) throws UnsupportedMessageException { + if (RRuntime.isForeignObject(obj)) { + if (ForeignAccess.sendIsNull(isNullNode, (TruffleObject) obj)) { + return RNull.instance; + } + Boolean isBoxed = (Boolean) ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) obj); + if (isBoxed) { + return RRuntime.java2R(ForeignAccess.sendUnbox(unboxNode, (TruffleObject) obj)); + } + } + return RRuntime.java2R(obj); + } + + public static Object read(Node caller, Object position, Node foreignRead, Node keyInfoNode, TruffleObject object, FirstStringNode firstString, CastStringNode castNode) + throws RError, InteropException { + if (position instanceof Integer) { + position = ((int) position) - 1; + } else if (position instanceof Double) { + position = ((double) position) - 1; + } else if (position instanceof RAbstractDoubleVector) { + position = ((RAbstractDoubleVector) position).getDataAt(0) - 1; + } else if (position instanceof RAbstractIntVector) { + position = ((RAbstractIntVector) position).getDataAt(0) - 1; + } else if (position instanceof RAbstractStringVector) { + position = firstString.executeString(castNode.doCast(position)); + } else if (!(position instanceof String)) { + throw RError.error(caller, RError.Message.GENERIC, "invalid index during foreign access"); + } + + int info = ForeignAccess.sendKeyInfo(keyInfoNode, object, position); + if (KeyInfo.isReadable(info)) { + return ForeignAccess.sendRead(foreignRead, object, position); + } else if (position instanceof String && !KeyInfo.isExisting(info) && JavaInterop.isJavaObject(Object.class, object)) { + TruffleObject clazz = JavaInterop.toJavaClass(object); + info = ForeignAccess.sendKeyInfo(keyInfoNode, clazz, position); + if (KeyInfo.isReadable(info)) { + return ForeignAccess.sendRead(foreignRead, clazz, position); + } + } + throw RError.error(caller, RError.Message.GENERIC, "invalid index/identifier during foreign access: " + position); + } + @Specialization(guards = {"cached != null", "cached.isSupported(vector, positions)"}) protected Object doExtractSameDimensions(VirtualFrame frame, RAbstractVector vector, Object[] positions, Object exact, Object dropDimensions, // @Cached("createRecursiveCache(vector, positions)") RecursiveExtractSubscriptNode cached) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCastNode.java index 06410a6a105a41dbe1d641bb9c4922a162873e9d..80e0e05b7b17ed0a4272a2ef163f6cdb8ef35610 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCastNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCastNode.java @@ -108,7 +108,7 @@ abstract class PositionCastNode extends Node { @Cached("create()") BoxPrimitiveNode box) { if (mode.isSubscript()) { // double gets casted to integer for subscript - return (RAbstractVector) box.execute(cast.execute(position)); + return (RAbstractVector) box.execute(cast.doCast(position)); } else { // because we need to perform a special bounds check with doubles // we cannot yet convert the double array to int for subsets diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCharacterLookupNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCharacterLookupNode.java index dbe39a3f17a56e743450227ff992883257b36447..d1566a34ef7d7e82285deaf7e11e5edddb106d54 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCharacterLookupNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCharacterLookupNode.java @@ -85,9 +85,9 @@ final class PositionCharacterLookupNode extends Node { private RError noDimNames() { if (mode.isSubset()) { - return RError.error(this, Message.NO_ARRAY_DIMNAMES); + throw RError.error(this, Message.NO_ARRAY_DIMNAMES); } else { - return RError.error(this, Message.SUBSCRIPT_BOUNDS); + throw RError.error(this, Message.SUBSCRIPT_BOUNDS); } } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java index e7c74e62eb3dd186919f77d1424cf2e04e41f081..f45d9018a6394c39ec670548a3d687d52059680a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java @@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.access.vector; import java.util.Arrays; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; @@ -143,7 +144,6 @@ abstract class PositionCheckSubsetNode extends PositionCheckNode { @Cached("create()") GetNamesAttributeNode getNamesNode, @Cached("create()") SetNamesAttributeNode setNamesNode) { RAbstractIntVector intPosition = RDataFactory.createIntVector(positionLength); - intPosition.setComplete(position.isComplete()); // requires names preservation RStringVector names = hasNamesProfile.profile(getNamesNode.getNames(position)); if (names != null) { @@ -203,6 +203,7 @@ abstract class PositionCheckSubsetNode extends PositionCheckNode { } intPosition.setDataAt(convertedStore, i, intPositionValue); } + intPosition.setComplete(!hasSeenNA); return doIntegerProfiled(profile, dimensionLength, intPosition, positionLength, hasSeenPositive, hasSeenNegative, hasSeenNA, outOfBoundsCount, zeroCount, maxOutOfBoundsIndex); } @@ -257,7 +258,7 @@ abstract class PositionCheckSubsetNode extends PositionCheckNode { } private final BranchProfile noZeroes = BranchProfile.create(); - private boolean checkForScalarPosition = true; + @CompilationFinal private boolean checkForScalarPosition = true; private RAbstractVector doIntegerProfiled(PositionProfile profile, int dimensionLength, RAbstractIntVector intPosition, int positionLength, boolean hasSeenPositive, boolean hasSeenNegative, boolean hasSeenNA, int outOfBoundsCount, int zeroCount, int maxOutOfBoundsIndex) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java index 799416e6408f0c4c6224c23e9145cea8e62eb2f3..34d28947e3f545c798d980c8e5b9c6d6f155df98 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.access.vector; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.Node; @@ -124,18 +125,19 @@ final class PositionsCheckNode extends Node { } private RError dimensionsError() { + CompilerDirectives.transferToInterpreter(); if (replace) { if (mode.isSubset()) { if (getDimensions() == 2) { - return RError.error(this, RError.Message.INCORRECT_SUBSCRIPTS_MATRIX); + throw RError.error(this, RError.Message.INCORRECT_SUBSCRIPTS_MATRIX); } else { - return RError.error(this, RError.Message.INCORRECT_SUBSCRIPTS); + throw RError.error(this, RError.Message.INCORRECT_SUBSCRIPTS); } } else { - return RError.error(this, RError.Message.IMPROPER_SUBSCRIPT); + throw RError.error(this, RError.Message.IMPROPER_SUBSCRIPT); } } else { - return RError.error(this, RError.Message.INCORRECT_DIMENSIONS); + throw RError.error(this, RError.Message.INCORRECT_DIMENSIONS); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.java index 025d674aa966ae616dea18fea9c4e772156b9d99..0e4e9b5030820afc3b8e39f7b87e81944dc86264 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.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 @@ -51,11 +51,11 @@ abstract class RecursiveSubscriptNode extends Node { protected final RError indexingFailed(int i) { errorBranch.enter(); - return RError.error(this, RError.Message.RECURSIVE_INDEXING_FAILED, i); + throw RError.error(this, RError.Message.RECURSIVE_INDEXING_FAILED, i); } protected final RError noSuchIndex(int i) { errorBranch.enter(); - return RError.error(this, RError.Message.NO_SUCH_INDEX, i); + throw RError.error(this, RError.Message.NO_SUCH_INDEX, i); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java index 03428c908e12d7675b48cfe2fbb093427c9672a2..77ce1d830a852c0c6074d374f4ef396aee94ef4d 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java @@ -25,12 +25,15 @@ package com.oracle.truffle.r.nodes.access.vector; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.InteropException; +import com.oracle.truffle.api.interop.KeyInfo; import com.oracle.truffle.api.interop.Message; import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.java.JavaInterop; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode; import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode; @@ -38,8 +41,6 @@ import com.oracle.truffle.r.nodes.unary.CastStringNode; import com.oracle.truffle.r.nodes.unary.FirstStringNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.RDouble; -import com.oracle.truffle.r.runtime.data.RInteger; import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @@ -49,6 +50,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; /** * Syntax node for element writes. */ +@ImportStatic({RRuntime.class, com.oracle.truffle.api.interop.Message.class}) public abstract class ReplaceVectorNode extends Node { protected static final int CACHE_LIMIT = 5; @@ -97,40 +99,57 @@ public abstract class ReplaceVectorNode extends Node { @Specialization(guards = {"isForeignObject(object)", "positions.length == cachedLength"}) protected Object accessField(TruffleObject object, Object[] positions, Object value, - @Cached("createForeignWrite(positions)") Node foreignRead, + @Cached("WRITE.createNode()") Node foreignWrite, + @Cached("READ.createNode()") Node foreignRead, + @Cached("KEY_INFO.createNode()") Node keyInfo, @SuppressWarnings("unused") @Cached("positions.length") int cachedLength, @Cached("create()") CastStringNode castNode, @Cached("createFirstString()") FirstStringNode firstString) { - - Object writtenValue = value; - if (writtenValue instanceof RInteger) { - writtenValue = ((RInteger) writtenValue).getValue(); - } else if (writtenValue instanceof RDouble) { - writtenValue = ((RDouble) writtenValue).getValue(); - } - Object position = positions[0]; + Object writtenValue = RRuntime.r2Java(value); try { - if (position instanceof Integer) { - return ForeignAccess.send(foreignRead, object, new Object[]{((Integer) position) - 1, writtenValue}); - } else if (position instanceof Double) { - return ForeignAccess.send(foreignRead, object, new Object[]{((Double) position) - 1, writtenValue}); - } else if (position instanceof String) { - return ForeignAccess.send(foreignRead, object, new Object[]{position, writtenValue}); - } else if (position instanceof RAbstractStringVector) { - String string = firstString.executeString(castNode.execute(position)); - return ForeignAccess.send(foreignRead, object, new Object[]{string, writtenValue}); - } else if (position instanceof RAbstractDoubleVector) { - return ForeignAccess.send(foreignRead, object, new Object[]{((RAbstractDoubleVector) position).getDataAt(0) - 1, writtenValue}); - } else if (position instanceof RAbstractIntVector) { - return ForeignAccess.send(foreignRead, object, new Object[]{((RAbstractIntVector) position).getDataAt(0) - 1, writtenValue}); - } else { - throw RError.error(this, RError.Message.GENERIC, "invalid index during foreign access"); + TruffleObject result = object; + for (int i = 0; i < positions.length - 1; i++) { + result = (TruffleObject) ExtractVectorNode.read(this, positions[i], foreignRead, keyInfo, result, firstString, castNode); } + write(positions[positions.length - 1], foreignWrite, keyInfo, result, writtenValue, firstString, castNode); + return object; } catch (InteropException e) { throw RError.interopError(RError.findParentRBase(this), e, object); } } + private void write(Object position, Node foreignWrite, Node keyInfoNode, TruffleObject object, Object writtenValue, FirstStringNode firstString, CastStringNode castNode) + throws InteropException, RError { + if (position instanceof Integer) { + position = ((Integer) position) - 1; + } else if (position instanceof Double) { + position = ((Double) position) - 1; + } else if (position instanceof RAbstractDoubleVector) { + position = ((RAbstractDoubleVector) position).getDataAt(0) - 1; + } else if (position instanceof RAbstractIntVector) { + position = ((RAbstractIntVector) position).getDataAt(0) - 1; + } else if (position instanceof RAbstractStringVector) { + String string = firstString.executeString(castNode.doCast(position)); + position = string; + } else if (!(position instanceof String)) { + throw RError.error(this, RError.Message.GENERIC, "invalid index during foreign access"); + } + + int info = ForeignAccess.sendKeyInfo(keyInfoNode, object, position); + if (KeyInfo.isWritable(info)) { + ForeignAccess.sendWrite(foreignWrite, object, position, RRuntime.r2Java(writtenValue)); + return; + } else if (position instanceof String && !KeyInfo.isExisting(info) && JavaInterop.isJavaObject(Object.class, object)) { + TruffleObject clazz = JavaInterop.toJavaClass(object); + info = ForeignAccess.sendKeyInfo(keyInfoNode, clazz, position); + if (KeyInfo.isWritable(info)) { + ForeignAccess.sendWrite(foreignWrite, clazz, position, RRuntime.r2Java(writtenValue)); + return; + } + } + throw RError.error(this, RError.Message.GENERIC, "invalid index/identifier during foreign access: " + position); + } + @Specialization(limit = "CACHE_LIMIT", guards = {"cached != null", "cached.isSupported(vector, positions)"}) protected Object doRecursive(VirtualFrame frame, RAbstractListVector vector, Object[] positions, Object value, // @Cached("createRecursiveCache(vector, positions)") RecursiveReplaceSubscriptNode cached) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccessNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccessNode.java index e2a414911323b364302744e8d9cb89adf778de82..a69ac1f254f3d89939a3b952845aa481a176578c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccessNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccessNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,19 +23,16 @@ package com.oracle.truffle.r.nodes.attributes; import com.oracle.truffle.api.CompilerAsserts; -import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.api.object.Location; import com.oracle.truffle.api.object.Property; import com.oracle.truffle.api.object.Shape; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.runtime.nodes.RBaseNode; /** * The base class for the nodes that get/set/remove attributes. It encapsulates the common methods * used in guards and for caching. */ -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) public abstract class AttributeAccessNode extends RBaseNode { protected AttributeAccessNode() { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeIterativeAccessNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeIterativeAccessNode.java index 5c3512aab3dc47b5d441e89dde30cfaf9ffd1e71..da7df67a31af6cde7de348744d84dca6034bc873 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeIterativeAccessNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeIterativeAccessNode.java @@ -24,13 +24,11 @@ package com.oracle.truffle.r.nodes.attributes; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.api.object.Property; import com.oracle.truffle.api.object.Shape; import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.runtime.data.RAttributesLayout; import com.oracle.truffle.r.runtime.data.RAttributesLayout.AttrsLayout; import com.oracle.truffle.r.runtime.nodes.RBaseNode; @@ -43,7 +41,6 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; * properties (i.e. attributes) it is unnecessary to invoke method {@link Shape#getPropertyList()}, * which would be more expensive. */ -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) public abstract class AttributeIterativeAccessNode extends RBaseNode { protected static final int CACHE_LIMIT = RAttributesLayout.LAYOUTS.length; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java index 4eb7f700caffe6e92dc54e0045fb443e0ef8e30c..4ad3dfb7616f78d0df1cd03b70a010f6b7ed38b7 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java @@ -41,7 +41,6 @@ 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.RIntVector; -import com.oracle.truffle.r.runtime.data.RInteger; import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; @@ -325,7 +324,6 @@ public final class SpecialAttributesFunctions { @Specialization(insertBefore = "setAttrInAttributable") protected void setNamesInVector(RAbstractVector x, RStringVector newNames, - @Cached("create()") BranchProfile namesTooLongProfile, @Cached("createBinaryProfile()") ConditionProfile useDimNamesProfile, @Cached("create()") GetDimAttributeNode getDimNode, @Cached("create()") SetDimNamesAttributeNode setDimNamesNode, @@ -335,8 +333,8 @@ public final class SpecialAttributesFunctions { @Cached("create()") ShareObjectNode updateRefCountNode) { RAbstractVector xProfiled = xTypeProfile.profile(x); if (newNames.getLength() > xProfiled.getLength()) { - namesTooLongProfile.enter(); - throw RError.error(this, RError.Message.ATTRIBUTE_VECTOR_SAME_LENGTH, RRuntime.NAMES_ATTR_KEY, newNames.getLength(), xProfiled.getLength()); + CompilerDirectives.transferToInterpreter(); + throw error(RError.Message.ATTRIBUTE_VECTOR_SAME_LENGTH, RRuntime.NAMES_ATTR_KEY, newNames.getLength(), xProfiled.getLength()); } int[] dimensions = getDimNode.getDimensions(x); @@ -466,9 +464,6 @@ public final class SpecialAttributesFunctions { public abstract static class SetDimAttributeNode extends SetSpecialAttributeNode { private final ConditionProfile nullDimProfile = ConditionProfile.createBinaryProfile(); - private final ConditionProfile naDimProfile = ConditionProfile.createBinaryProfile(); - private final ConditionProfile negativeDimProfile = ConditionProfile.createBinaryProfile(); - private final ConditionProfile dimNotMatchLengthProfile = ConditionProfile.createBinaryProfile(); private final ValueProfile contArgClassProfile = ValueProfile.createClassProfile(); private final ValueProfile dimArgClassProfile = ValueProfile.createClassProfile(); private final LoopConditionProfile verifyLoopProfile = LoopConditionProfile.createCountingProfile(); @@ -552,14 +547,13 @@ public final class SpecialAttributesFunctions { private void verifyOneDimensions(int vectorLength, int dim) { int length = dim; - if (naDimProfile.profile(RRuntime.isNA(dim))) { - throw RError.error(this, RError.Message.DIMS_CONTAIN_NA); - } else if (negativeDimProfile.profile(dim < 0)) { - throw RError.error(this, RError.Message.DIMS_CONTAIN_NEGATIVE_VALUES); + if (RRuntime.isNA(dim)) { + throw error(RError.Message.DIMS_CONTAIN_NA); + } else if (dim < 0) { + throw error(RError.Message.DIMS_CONTAIN_NEGATIVE_VALUES); } - if (dimNotMatchLengthProfile.profile(length != vectorLength && vectorLength > 0)) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.DIMS_DONT_MATCH_LENGTH, length, vectorLength); + if (length != vectorLength && vectorLength > 0) { + throw error(RError.Message.DIMS_DONT_MATCH_LENGTH, length, vectorLength); } } @@ -570,18 +564,15 @@ public final class SpecialAttributesFunctions { int length = 1; for (int i = 0; i < dimLen; i++) { int dim = dimsProfiled.getDataAt(i); - if (naDimProfile.profile(RRuntime.isNA(dim))) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.DIMS_CONTAIN_NA); - } else if (negativeDimProfile.profile(dim < 0)) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.DIMS_CONTAIN_NEGATIVE_VALUES); + if (RRuntime.isNA(dim)) { + throw error(RError.Message.DIMS_CONTAIN_NA); + } else if (dim < 0) { + throw error(RError.Message.DIMS_CONTAIN_NEGATIVE_VALUES); } length *= dim; } if (length != vectorLength && vectorLength > 0) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.DIMS_DONT_MATCH_LENGTH, length, vectorLength); + throw error(RError.Message.DIMS_DONT_MATCH_LENGTH, length, vectorLength); } } } @@ -610,7 +601,6 @@ public final class SpecialAttributesFunctions { private final ConditionProfile nullDimsProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile nonEmptyDimsProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile twoDimsOrMoreProfile = ConditionProfile.createBinaryProfile(); - private final ConditionProfile isContainerProfile = ConditionProfile.createBinaryProfile(); protected GetDimAttributeNode() { super(RRuntime.DIM_ATTR_KEY); @@ -680,7 +670,7 @@ public final class SpecialAttributesFunctions { } public int nrows(Object x) { - if (isContainerProfile.profile(x instanceof RAbstractContainer)) { + if (x instanceof RAbstractContainer) { RAbstractContainer xa = (RAbstractContainer) x; int[] dims = getDimensions(xa); if (nonEmptyDimsProfile.profile(dims != null && dims.length > 0)) { @@ -689,12 +679,12 @@ public final class SpecialAttributesFunctions { return xa.getLength(); } } else { - throw RError.error(RError.SHOW_CALLER2, RError.Message.OBJECT_NOT_MATRIX); + throw error(RError.Message.OBJECT_NOT_MATRIX); } } public int ncols(Object x) { - if (isContainerProfile.profile(x instanceof RAbstractContainer)) { + if (x instanceof RAbstractContainer) { RAbstractContainer xa = (RAbstractContainer) x; int[] dims = getDimensions(xa); if (nonEmptyDimsProfile.profile(dims != null && dims.length > 0)) { @@ -707,7 +697,7 @@ public final class SpecialAttributesFunctions { return 1; } } else { - throw RError.error(RError.SHOW_CALLER2, RError.Message.OBJECT_NOT_MATRIX); + throw error(RError.Message.OBJECT_NOT_MATRIX); } } } @@ -753,10 +743,7 @@ public final class SpecialAttributesFunctions { @Specialization(insertBefore = "setAttrInAttributable") protected void setDimNamesInVector(RVector<?> x, RList newDimNames, @Cached("create()") GetDimAttributeNode getDimNode, - @Cached("create()") BranchProfile nullDimsProfile, - @Cached("create()") BranchProfile dimsLengthProfile, @Cached("createCountingProfile()") LoopConditionProfile loopProfile, - @Cached("create()") BranchProfile invalidDimProfile, @Cached("create()") BranchProfile nullDimProfile, @Cached("create()") BranchProfile resizeDimsProfile, @Cached("create()") BranchProfile attrNullProfile, @@ -765,14 +752,12 @@ public final class SpecialAttributesFunctions { @Cached("create()") ShareObjectNode updateRefCountNode) { int[] dimensions = getDimNode.getDimensions(x); if (dimensions == null) { - nullDimsProfile.enter(); - throw RError.error(this, RError.Message.DIMNAMES_NONARRAY); + throw error(RError.Message.DIMNAMES_NONARRAY); } int newDimNamesLength = newDimNames.getLength(); if (newDimNamesLength > dimensions.length) { - dimsLengthProfile.enter(); - throw RError.error(this, RError.Message.DIMNAMES_DONT_MATCH_DIMS, newDimNamesLength, - dimensions.length); + CompilerDirectives.transferToInterpreter(); + throw error(RError.Message.DIMNAMES_DONT_MATCH_DIMS, newDimNamesLength, dimensions.length); } loopProfile.profileCounted(newDimNamesLength); @@ -781,8 +766,8 @@ public final class SpecialAttributesFunctions { if ((dimObject instanceof String && dimensions[i] != 1) || (dimObject instanceof RStringVector && !isValidDimLength((RStringVector) dimObject, dimensions[i]))) { - invalidDimProfile.enter(); - throw RError.error(this, RError.Message.DIMNAMES_DONT_MATCH_EXTENT, i + 1); + CompilerDirectives.transferToInterpreter(); + throw error(RError.Message.DIMNAMES_DONT_MATCH_EXTENT, i + 1); } if (dimObject == null || (dimObject instanceof RStringVector && ((RStringVector) dimObject).getLength() == 0)) { @@ -1077,21 +1062,9 @@ public final class SpecialAttributesFunctions { for (int i = 0; i < classAttr.getLength(); i++) { String attr = classAttr.getDataAt(i); if (RRuntime.CLASS_FACTOR.equals(attr)) { - // TODO: Isn't this redundant when the same operation is done after the - // loop? - if (!initializeAttrs) { - super.setAttrInAttributable(vector, classAttr, nullAttrProfile, attrStorageProfile, xTypeProfile, updateRefCountNode); - } - if (vector.getElementClass() != RInteger.class) { - // N.B. there used to be conversion to integer under certain - // circumstances. - // However, it seems that it was dead/obsolete code so it was removed. - // Notes: this can only happen if the class is set by hand to some - // non-integral vector, i.e. attr(doubles, 'class') <- 'factor'. GnuR - // also - // does not update the 'class' attr with other, possibly - // valid classes when it reaches this error. - throw RError.error(RError.SHOW_CALLER2, RError.Message.ADDING_INVALID_CLASS, "factor"); + if (!(vector instanceof RAbstractIntVector)) { + CompilerDirectives.transferToInterpreter(); + throw error(RError.Message.ADDING_INVALID_CLASS, "factor"); } } } @@ -1143,11 +1116,5 @@ public final class SpecialAttributesFunctions { public final boolean isObject(Object x) { return getClassAttr(x) != null ? true : false; } - - public final RStringVector getClassHierarchy(RAttributable x) { - Object v = execute(x); - RStringVector result = v instanceof RStringVector ? (RStringVector) v : x.getImplicitClass(); - return result != null ? result : RDataFactory.createEmptyStringVector(); - } } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java index cbf0003eecd8b8e5b9efc923888ecbf2d9be2c6a..56f24c6840969e6049dfd536a99694f3c015011e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java @@ -45,6 +45,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; import com.oracle.truffle.r.runtime.ops.BinaryArithmeticFactory; import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory; @@ -54,22 +55,29 @@ import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory; * operation is implemented by factory object given as a constructor parameter, e.g. * {@link com.oracle.truffle.r.runtime.ops.BinaryArithmetic.Add} */ -public abstract class BinaryArithmeticNode extends RBuiltinNode { +public abstract class BinaryArithmeticNode extends RBuiltinNode.Arg2 { protected static final int CACHE_LIMIT = 5; protected final BinaryArithmeticFactory binary; private final UnaryArithmeticFactory unary; + static { + Casts casts = new Casts(BinaryArithmeticNode.class); + casts.arg(0).boxPrimitive(); + casts.arg(1).boxPrimitive(); + } + public BinaryArithmeticNode(BinaryArithmeticFactory binaryFactory, UnaryArithmeticFactory unaryFactory) { this.binary = binaryFactory; this.unary = unaryFactory; } - static { - Casts casts = new Casts(BinaryArithmeticNode.class); - casts.arg(0).boxPrimitive(); - casts.arg(1).boxPrimitive(); + public abstract Object execute(Object left, Object right); + + @Override + public RBaseNode getErrorContext() { + return this; } public static BinaryArithmeticNode create(BinaryArithmeticFactory binary, UnaryArithmeticFactory unary) { @@ -111,7 +119,7 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode { protected final UnaryArithmeticNode createUnaryArithmeticNode() { if (unary == null) { - throw RError.error(this, RError.Message.ARGUMENT_EMPTY, 2); + throw error(RError.Message.ARGUMENT_EMPTY, 2); } else { CompilerDirectives.transferToInterpreterAndInvalidate(); return UnaryArithmeticNodeGen.create(unary, RError.Message.INVALID_ARG_TYPE_UNARY); @@ -141,7 +149,7 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode { @Fallback protected Object doInvalidType(@SuppressWarnings("unused") Object left, @SuppressWarnings("unused") Object right) { - throw RError.error(this, Message.NON_NUMERIC_BINARY); + throw error(Message.NON_NUMERIC_BINARY); } protected static BinaryMapNode createCached(BinaryArithmetic innerArithmetic, Object left, Object right) { @@ -167,10 +175,11 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode { public BinaryMapNode get(BinaryArithmetic arithmetic, RAbstractVector left, RAbstractVector right) { CompilerAsserts.neverPartOfCompilation(); - if (!cached.isSupported(left, right)) { - cached = cached.replace(createCached(arithmetic, left, right)); + BinaryMapNode map = cached; + if (!map.isSupported(left, right)) { + cached = map = map.replace(createCached(arithmetic, left, right)); } - return cached; + return map; } } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java index 25ecda988042ac0c84421d5c573dfe322cc38cb5..ee507eba25d5427948199f6d1d3654836b3e5549 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java @@ -23,13 +23,12 @@ package com.oracle.truffle.r.nodes.binary; import com.oracle.truffle.api.CompilerDirectives; + import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.nodes.binary.BinaryArithmeticSpecialNodeGen.IntegerBinaryArithmeticSpecialNodeGen; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RSpecialFactory; @@ -43,27 +42,26 @@ import com.oracle.truffle.r.runtime.ops.BinaryArithmeticFactory; * handling, which is replicated here, others (notably pow and mul) throw * {@link RSpecialFactory#throwFullCallNeeded()} on NA. */ -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) -@NodeChild(value = "arguments", type = RNode[].class) +@NodeChild(value = "left", type = RNode.class) +@NodeChild(value = "right", type = RNode.class) public abstract class BinaryArithmeticSpecial extends RNode { + private final boolean handleNA; @Child private BinaryArithmetic operation; - public BinaryArithmeticSpecial(BinaryArithmetic operation, boolean handleNA) { - this.operation = operation; - this.handleNA = handleNA; + public BinaryArithmeticSpecial(BinaryArithmeticFactory opFactory) { + this.operation = opFactory.createOperation(); + this.handleNA = !(opFactory == BinaryArithmetic.POW || opFactory == BinaryArithmetic.MOD); } - public static RSpecialFactory createSpecialFactory(final BinaryArithmeticFactory opFactory) { - final boolean handleNA = !(opFactory == BinaryArithmetic.POW || opFactory == BinaryArithmetic.MOD); + public static RSpecialFactory createSpecialFactory(BinaryArithmeticFactory opFactory) { boolean handleIntegers = !(opFactory == BinaryArithmetic.POW || opFactory == BinaryArithmetic.DIV); if (handleIntegers) { return (signature, arguments, inReplacement) -> signature.getNonNullCount() == 0 && arguments.length == 2 - ? IntegerBinaryArithmeticSpecialNodeGen.create(opFactory.createOperation(), handleNA, arguments) : null; + ? IntegerBinaryArithmeticSpecialNodeGen.create(opFactory, arguments[0], arguments[1]) : null; } else { return (signature, arguments, inReplacement) -> signature.getNonNullCount() == 0 && arguments.length == 2 - ? BinaryArithmeticSpecialNodeGen.create(opFactory.createOperation(), handleNA, arguments) - : null; + ? BinaryArithmeticSpecialNodeGen.create(opFactory, arguments[0], arguments[1]) : null; } } @@ -78,7 +76,7 @@ public abstract class BinaryArithmeticSpecial extends RNode { @Fallback @SuppressWarnings("unused") - protected void doFallback(Object left, Object right) { + protected double doFallback(Object left, Object right) { throw RSpecialFactory.throwFullCallNeeded(); } @@ -100,11 +98,10 @@ public abstract class BinaryArithmeticSpecial extends RNode { /** * Adds integers handling. */ - @TypeSystemReference(EmptyTypeSystemFlatLayout.class) abstract static class IntegerBinaryArithmeticSpecial extends BinaryArithmeticSpecial { - IntegerBinaryArithmeticSpecial(BinaryArithmetic op, boolean handleNA) { - super(op, handleNA); + IntegerBinaryArithmeticSpecial(BinaryArithmeticFactory opFactory) { + super(opFactory); } @Specialization 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 1101328086708d74d6745c6aa393474f5d8bd352..1f317668577066be9db826c1ae0ee1dce1e65fa2 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 @@ -45,6 +45,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.ops.BinaryLogic; import com.oracle.truffle.r.runtime.ops.BinaryLogic.And; import com.oracle.truffle.r.runtime.ops.BinaryLogic.Or; @@ -56,7 +57,7 @@ import com.oracle.truffle.r.runtime.ops.BooleanOperationFactory; * operation is implemented by factory object given as a constructor parameter, e.g. * {@link com.oracle.truffle.r.runtime.ops.BinaryLogic.And}. */ -public abstract class BinaryBooleanNode extends RBuiltinNode { +public abstract class BinaryBooleanNode extends RBuiltinNode.Arg2 { protected static final int CACHE_LIMIT = 5; @@ -72,6 +73,11 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { casts.arg(1).boxPrimitive(); } + @Override + public RBaseNode getErrorContext() { + return this; + } + private static boolean isLogicOp(BooleanOperation op) { return op instanceof And || op instanceof Or; } @@ -80,6 +86,7 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { return factory == BinaryLogic.AND || factory == BinaryLogic.OR; } + @Override public abstract Object execute(VirtualFrame frame, Object left, Object right); public static BinaryBooleanNode create(BooleanOperationFactory factory) { @@ -159,7 +166,7 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { @SuppressWarnings("unused") @Specialization(guards = {"(isRMissing(left) || isRMissing(right))"}) protected Object doOneArg(Object left, Object right) { - throw RError.error(this, RError.Message.IS_OF_WRONG_ARITY, 1, factory.createOperation().opName(), 2); + throw error(RError.Message.IS_OF_WRONG_ARITY, 1, factory.createOperation().opName(), 2); } protected static boolean isRNullOrEmptyAndNotMissing(Object left, Object right) { @@ -177,7 +184,7 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { @SuppressWarnings("unused") @Fallback protected Object doInvalidType(Object left, Object right) { - throw RError.error(this, Message.OPERATIONS_NUMERIC_LOGICAL_COMPLEX); + throw error(Message.OPERATIONS_NUMERIC_LOGICAL_COMPLEX); } protected static BinaryMapNode createCached(BooleanOperation operation, Object left, Object right) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java index 3026310ff21bd27440abc320c7cb1fd058d55a31..444696a3f70eddfded9e68f72af65a821195e2c9 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java @@ -44,7 +44,7 @@ import com.oracle.truffle.r.runtime.ops.BooleanOperation; import com.oracle.truffle.r.runtime.ops.BooleanOperationFactory; import com.oracle.truffle.r.runtime.ops.na.NACheck; -public abstract class BinaryBooleanScalarNode extends RBuiltinNode { +public abstract class BinaryBooleanScalarNode extends RBuiltinNode.Arg2 { /* * As the execution of right depends on the left value and the right node might be arbitrarily diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanSpecial.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanSpecial.java index d2f20e7dc55291c899d70ea270a008d20919a044..00075ef4481d84450784193b99ffb80114770b5f 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanSpecial.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanSpecial.java @@ -25,8 +25,6 @@ package com.oracle.truffle.r.nodes.binary; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.dsl.TypeSystemReference; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RSpecialFactory; import com.oracle.truffle.r.runtime.nodes.RNode; @@ -38,7 +36,6 @@ import com.oracle.truffle.r.runtime.ops.BooleanOperationFactory; * empty type system to avoid conversions to vector types. NA values cause * {@link RSpecialFactory#throwFullCallNeeded()} exception. */ -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) @NodeChild(value = "arguments", type = RNode[].class) public abstract class BinaryBooleanSpecial extends RNode { @Child private BooleanOperation operation; @@ -85,7 +82,7 @@ public abstract class BinaryBooleanSpecial extends RNode { @Fallback @SuppressWarnings("unused") - public void doFallback(Object left, Object right) { + public byte doFallback(Object left, Object right) { throw RSpecialFactory.throwFullCallNeeded(); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryMapArithmeticFunctionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryMapArithmeticFunctionNode.java index c5e9599bc49d072c300f1356b238fca75a803924..ab8aefdb1e26d9e8ece28959285713a66da9dd41 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryMapArithmeticFunctionNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryMapArithmeticFunctionNode.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 @@ -162,9 +162,9 @@ public final class BinaryMapArithmeticFunctionNode extends BinaryMapNAFunctionNo return RDataFactory.createComplexRealOne(); } else if (this.arithmetic instanceof BinaryArithmetic.Mod) { // CORNER: Must throw error on modulo operation on complex numbers. - throw RError.error(this, RError.Message.UNIMPLEMENTED_COMPLEX); + throw error(RError.Message.UNIMPLEMENTED_COMPLEX); } - return RRuntime.createComplexNA(); + return RComplex.createNA(); } if (rightNACheck.check(right)) { if (this.arithmetic instanceof BinaryArithmetic.Pow && left.isZero()) { @@ -172,9 +172,9 @@ public final class BinaryMapArithmeticFunctionNode extends BinaryMapNAFunctionNo return RDataFactory.createComplex(Double.NaN, Double.NaN); } else if (this.arithmetic instanceof BinaryArithmetic.Mod) { // CORNER: Must throw error on modulo operation on complex numbers. - throw RError.error(this, RError.Message.UNIMPLEMENTED_COMPLEX); + throw error(RError.Message.UNIMPLEMENTED_COMPLEX); } - return RRuntime.createComplexNA(); + return RComplex.createNA(); } try { RComplex value = arithmetic.op(left.getRealPart(), left.getImaginaryPart(), right.getRealPart(), right.getImaginaryPart()); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BoxPrimitiveNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BoxPrimitiveNode.java index 192e48d595c2400a4985a13466b9d210bf4085a1..b00a944834360e71708f0c11669cacf2f0b5983e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BoxPrimitiveNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BoxPrimitiveNode.java @@ -44,28 +44,28 @@ public abstract class BoxPrimitiveNode extends CastNode { } @Specialization - protected static RAbstractVector doInt(int vector) { + protected static RInteger doInt(int vector) { return RInteger.valueOf(vector); } @Specialization - protected static RAbstractVector doDouble(double vector) { + protected static RDouble doDouble(double vector) { return RDouble.valueOf(vector); } @Specialization - protected static RAbstractVector doLogical(byte vector) { + protected static RLogical doLogical(byte vector) { return RLogical.valueOf(vector); } @Specialization - protected static RAbstractVector doString(String value) { + protected static RString doString(String value) { return RString.valueOf(value); } /* * For the limit we use the number of primitive specializations - 1. After that its better to - * check !isPrimitve. + * check !isPrimitive. */ @Specialization(limit = "3", guards = "vector.getClass() == cachedClass") protected static Object doCached(Object vector, diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java index 3b823312a6187ee801e7e9346a400331215b565e..65e0a251a686ca0150292f619be37dd2f3af7466 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java @@ -14,6 +14,7 @@ package com.oracle.truffle.r.nodes.binary; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.r.nodes.unary.CastComplexNodeGen; import com.oracle.truffle.r.nodes.unary.CastDoubleNodeGen; import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen; @@ -25,9 +26,12 @@ import com.oracle.truffle.r.nodes.unary.CastStringNodeGen; import com.oracle.truffle.r.nodes.unary.TypeofNode; import com.oracle.truffle.r.nodes.unary.TypeofNodeGen; import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.data.RTypes; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; -public abstract class CastTypeNode extends BinaryNode { +@TypeSystemReference(RTypes.class) +public abstract class CastTypeNode extends RBaseNode { protected static final int NUMBER_OF_TYPES = RType.values().length; @@ -46,7 +50,7 @@ public abstract class CastTypeNode extends BinaryNode { protected static Object doCast(RAbstractVector value, RType type, @Cached("type") RType cachedType, @Cached("createCast(cachedType)") CastNode cast) { - return cast.execute(value); + return cast.doCast(value); } @SuppressWarnings("unused") @@ -63,7 +67,7 @@ public abstract class CastTypeNode extends BinaryNode { } public static CastTypeNode create() { - return CastTypeNodeGen.create(null, null); + return CastTypeNodeGen.create(); } @TruffleBoundary diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java index 98aedf151d9e5d4d1441b6b3313700816ca26755..965ea3aa0343b8228cbad4d89ebaf6c77639dad6 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java @@ -23,7 +23,6 @@ package com.oracle.truffle.r.nodes.builtin; import java.util.Arrays; -import java.util.function.Consumer; import java.util.function.Function; import com.oracle.truffle.api.CompilerAsserts; @@ -82,7 +81,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; public final class CastBuilder { @@ -134,6 +132,16 @@ public final class CastBuilder { return castNodes; } + /** + * The argument pipeline builders are needed when analyzing pipelines without instantiating + * them. It's useful in tests. + * + * @return the arguments cast pipeline builders + */ + public PipelineBuilder[] getPipelineBuilders() { + return argumentBuilders; + } + // --------------------- // The cast-pipelines API starts here @@ -148,8 +156,7 @@ public final class CastBuilder { * * In the pre-initial phase one can configure the overall behavior of the pipeline. Currently, * only the default handling of {@code RNull} and {@code RMissing} values can be overridden (the - * default behavior is explained below). The pipeline can be configured using - * {@link PreinitialPhaseBuilder#conf(Consumer)} or any other method of the + * default behavior is explained below). The pipeline can be configured using any method of the * {@link PreinitialPhaseBuilder} class, e.g. {@link PreinitialPhaseBuilder#allowNull()}. * </p> * <p> @@ -277,20 +284,20 @@ public final class CastBuilder { return filter1.or(filter2); } - public static <T, R extends T> PipelineStep<T, R> mustBe(Filter<T, R> argFilter, RBaseNode callObj, RError.Message message, Object... messageArgs) { - return new FilterStep<>(argFilter, new MessageData(callObj, message, messageArgs), false); + public static <T, R extends T> PipelineStep<T, R> mustBe(Filter<T, R> argFilter, RError.Message message, Object... messageArgs) { + return new FilterStep<>(argFilter, new MessageData(message, messageArgs), false); } public static <T, R extends T> PipelineStep<T, R> mustBe(Filter<T, R> argFilter) { - return mustBe(argFilter, null, null); + return new FilterStep<>(argFilter, null, false); } - public static <T> PipelineStep<T, T> shouldBe(Filter<T, ? extends T> argFilter, RBaseNode callObj, RError.Message message, Object... messageArgs) { - return new FilterStep<>(argFilter, new MessageData(callObj, message, messageArgs), true); + public static <T> PipelineStep<T, T> shouldBe(Filter<T, ? extends T> argFilter, RError.Message message, Object... messageArgs) { + return new FilterStep<>(argFilter, new MessageData(message, messageArgs), true); } public static <T> PipelineStep<T, T> shouldBe(Filter<T, ? extends T> argFilter) { - return shouldBe(argFilter, null, null); + return new FilterStep<>(argFilter, null, true); } public static <T, R> PipelineStep<T, R> map(Mapper<T, R> mapper) { @@ -321,50 +328,26 @@ public final class CastBuilder { return new CoercionStep<>(RType.Integer, false); } - public static <T> PipelineStep<T, Integer> asInteger(RBaseNode messageCallerObj) { - return new CoercionStep<>(RType.Integer, false, false, false, false, true, messageCallerObj); - } - public static <T> PipelineStep<T, RAbstractIntVector> asIntegerVector() { return new CoercionStep<>(RType.Integer, true); } - public static <T> PipelineStep<T, RAbstractIntVector> asIntegerVector(RBaseNode messageCallerObj) { - return new CoercionStep<>(RType.Integer, true, false, false, false, true, messageCallerObj); - } - public static <T> PipelineStep<T, RAbstractIntVector> asIntegerVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - return new CoercionStep<>(RType.Integer, true, preserveNames, preserveDimensions, preserveAttributes, true, null); - } - - public static <T> PipelineStep<T, RAbstractIntVector> asIntegerVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) { - return new CoercionStep<>(RType.Integer, true, preserveNames, preserveDimensions, preserveAttributes, true, messageCallerObj); + return new CoercionStep<>(RType.Integer, true, preserveNames, preserveDimensions, preserveAttributes, true); } public static <T> PipelineStep<T, Double> asDouble() { return new CoercionStep<>(RType.Double, false); } - public static <T> PipelineStep<T, Double> asDouble(RBaseNode messageCallerObj) { - return new CoercionStep<>(RType.Double, false, false, false, false, true, messageCallerObj); - } - public static <T> PipelineStep<T, RAbstractDoubleVector> asDoubleVector() { return new CoercionStep<>(RType.Double, true); } - public static <T> PipelineStep<T, RAbstractDoubleVector> asDoubleVector(RBaseNode messageCallerObj) { - return new CoercionStep<>(RType.Double, true, false, false, false, true, messageCallerObj); - } - public static <T> PipelineStep<T, RAbstractDoubleVector> asDoubleVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { return new CoercionStep<>(RType.Double, true, preserveNames, preserveDimensions, preserveAttributes); } - public static <T> PipelineStep<T, RAbstractDoubleVector> asDoubleVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) { - return new CoercionStep<>(RType.Double, true, preserveNames, preserveDimensions, preserveAttributes, true, messageCallerObj); - } - public static <T> PipelineStep<T, String> asString() { return new CoercionStep<>(RType.Character, false); } @@ -381,10 +364,6 @@ public final class CastBuilder { return new CoercionStep<>(RType.Complex, true); } - public static <T> PipelineStep<T, RAbstractComplexVector> asComplex(RBaseNode messageCallerObj) { - return new CoercionStep<>(RType.Complex, false, false, false, false, true, messageCallerObj); - } - public static <T> PipelineStep<T, RAbstractRawVector> asRawVector() { return new CoercionStep<>(RType.Raw, true); } @@ -393,24 +372,12 @@ public final class CastBuilder { return new CoercionStep<>(RType.Logical, false); } - public static <T> PipelineStep<T, Byte> asLogical(RBaseNode messageCallerObj) { - return new CoercionStep<>(RType.Logical, false, false, false, false, true, messageCallerObj); - } - public static <T> PipelineStep<T, RAbstractLogicalVector> asLogicalVector() { return new CoercionStep<>(RType.Logical, true); } - public static <T> PipelineStep<T, RAbstractLogicalVector> asLogicalVector(RBaseNode messageCallerObj) { - return new CoercionStep<>(RType.Logical, true, false, false, false, true, messageCallerObj); - } - public static <T> PipelineStep<T, RAbstractLogicalVector> asLogicalVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - return new CoercionStep<>(RType.Logical, true, preserveNames, preserveDimensions, preserveAttributes, false, null); - } - - public static <T> PipelineStep<T, RAbstractLogicalVector> asLogicalVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) { - return new CoercionStep<>(RType.Logical, true, preserveNames, preserveDimensions, preserveAttributes, true, messageCallerObj); + return new CoercionStep<>(RType.Logical, true, preserveNames, preserveDimensions, preserveAttributes, false); } public static PipelineStep<Byte, Boolean> asBoolean() { @@ -422,15 +389,7 @@ public final class CastBuilder { } public static <T> PipelineStep<T, RAbstractVector> asVector(boolean preserveNonVector) { - return new CoercionStep<>(RType.Any, true, false, false, false, preserveNonVector, null); - } - - /** - * Version of {@code findFirst} step that can be used in {@code chain}, must be followed by - * call for {@code xyzElement()}. - */ - public static <V extends RAbstractVector> FindFirstNodeBuilder findFirst(RBaseNode callObj, RError.Message message, Object... messageArgs) { - return new FindFirstNodeBuilder(callObj, message, messageArgs); + return new CoercionStep<>(RType.Any, true, false, false, false, preserveNonVector); } /** @@ -438,7 +397,7 @@ public final class CastBuilder { * call for {@code xyzElement()}. */ public static <V extends RAbstractVector> FindFirstNodeBuilder findFirst(RError.Message message, Object... messageArgs) { - return new FindFirstNodeBuilder(null, message, messageArgs); + return new FindFirstNodeBuilder(new MessageData(message, messageArgs)); } /** @@ -446,33 +405,29 @@ public final class CastBuilder { * call for {@code xyzElement()}. */ public static <V extends RAbstractVector> FindFirstNodeBuilder findFirst() { - return new FindFirstNodeBuilder(null, null, null); + return new FindFirstNodeBuilder(null); } - public static <T> PipelineStep<T, T> notNA(RBaseNode callObj, RError.Message message, Object... messageArgs) { - return notNA(null, callObj, message, messageArgs); + public static <T> PipelineStep<T, T> mustNotBeNA(RError.Message message, Object... messageArgs) { + return new NotNAStep<>(null, new MessageData(message, messageArgs)); } - public static <T> PipelineStep<T, T> notNA(RError.Message message, Object... messageArgs) { - return notNA(null, null, message, messageArgs); + public static <T> PipelineStep<T, T> shouldNotBeNA(T naReplacement, RError.Message message, Object... messageArgs) { + return new NotNAStep<>(naReplacement, new MessageData(message, messageArgs)); } - public static <T> PipelineStep<T, T> notNA(T naReplacement, RBaseNode callObj, RError.Message message, Object... messageArgs) { - return new NotNAStep<>(naReplacement, new MessageData(callObj, message, messageArgs)); - } - - public static <T> PipelineStep<T, T> notNA(T naReplacement, RError.Message message, Object... messageArgs) { - return notNA(naReplacement, null, message, messageArgs); - } - - public static <T> PipelineStep<T, T> notNA(T naReplacement) { + public static <T> PipelineStep<T, T> replaceNA(T naReplacement) { return new NotNAStep<>(naReplacement, null); } - public static <T> PipelineStep<T, T> notNA() { + public static <T> PipelineStep<T, T> mustNotBeNA() { return new NotNAStep<>(null, null); } + public static <T> PipelineStep<T, T> boxPrimitive() { + return new PipelineStep.BoxPrimitiveStep<>(); + } + public static NullFilter nullValue() { return NullFilter.INSTANCE; } @@ -481,10 +436,6 @@ public final class CastBuilder { return MissingFilter.INSTANCE; } - public static <T> CompareFilter<T> sameAs(T x) { - return new CompareFilter<>(CompareFilter.SAME, new CompareFilter.ScalarValue(x, RType.Any)); - } - public static <T> CompareFilter<T> equalTo(T x) { return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.ScalarValue(x, RType.Any)); } @@ -594,19 +545,19 @@ public final class CastBuilder { } public static CompareFilter<Integer> eq(int x) { - return new CompareFilter<>(CompareFilter.SAME, new CompareFilter.ScalarValue(x, RType.Integer)); + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.ScalarValue(x, RType.Integer)); } public static CompareFilter<Double> eq(double x) { - return new CompareFilter<>(CompareFilter.SAME, new CompareFilter.ScalarValue(x, RType.Double)); + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.ScalarValue(x, RType.Double)); } public static CompareFilter<Byte> eq(byte x) { - return new CompareFilter<>(CompareFilter.SAME, new CompareFilter.ScalarValue(x, RType.Logical)); + return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.ScalarValue(x, RType.Logical)); } public static CompareFilter<String> eq(String x) { - return new CompareFilter<>(CompareFilter.SAME, new CompareFilter.ScalarValue(x, RType.Character)); + return new CompareFilter<>(CompareFilter.STRING_EQ, new CompareFilter.ScalarValue(x, RType.Character)); } public static NotFilter<Integer> neq(int x) { @@ -750,7 +701,11 @@ public final class CastBuilder { } public static MapByteToBoolean toBoolean() { - return MapByteToBoolean.INSTANCE; + return new MapByteToBoolean(true); + } + + public static MapByteToBoolean toBoolean(boolean naReplacement) { + return new MapByteToBoolean(naReplacement); } public static MapDoubleToInt doubleToInt() { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java index 16694345d4e53e6f2b41047e2dae9db567cce76f..7fceec433df39e63feb9c9b22ecee7b34d0a9d07 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java @@ -33,7 +33,6 @@ import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.nodes.control.OperatorNode; import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode; import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; -import com.oracle.truffle.r.nodes.unary.CastNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; @@ -45,6 +44,7 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.REmpty; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant; @@ -146,7 +146,8 @@ public abstract class InternalNode extends OperatorNode { // verify the number of arguments if (factory.getSignature().getVarArgCount() == 0) { if (callArgs.length != factory.getSignature().getLength()) { - throw RError.error(RError.SHOW_CALLER, Message.ARGUMENTS_PASSED, callArgs.length, ".Internal(" + name + ")", factory.getSignature().getLength()); + throw RError.error(RError.SHOW_CALLER, callArgs.length == 1 ? Message.ARGUMENT_PASSED : Message.ARGUMENTS_PASSED, callArgs.length, ".Internal(" + name + ")", + factory.getSignature().getLength()); } for (int i = 0; i < callArgs.length; i++) { if (callArgs[i] instanceof RSyntaxConstant && ((RSyntaxConstant) callArgs[i]).getValue() == REmpty.instance) { @@ -192,7 +193,6 @@ public abstract class InternalNode extends OperatorNode { protected final int varArgIndex; @Children protected final RNode[] arguments; - @Children protected final CastNode[] casts; @Child private RBuiltinNode builtin; @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); @@ -200,22 +200,23 @@ public abstract class InternalNode extends OperatorNode { super(src, operator, outerSignature, outerArgs); this.factory = factory; this.builtin = factory.getConstructor().get(); - this.casts = builtin.getCasts(); this.arguments = new RNode[args.length]; for (int i = 0; i < args.length; i++) { arguments[i] = ((RSyntaxNode) args[i]).asRNode(); } this.varArgIndex = factory.getSignature().getVarArgIndex(); - if (varArgIndex != ArgumentsSignature.NO_VARARG) { - assert casts.length <= varArgIndex || casts[varArgIndex] == null : "no casts on '...' arguments to .Internals"; - } + } + + @Override + protected RBaseNode getErrorContext() { + return builtin.getErrorContext(); } protected abstract Object[] prepareArgs(VirtualFrame frame); @Override public Object execute(VirtualFrame frame) { - Object result = builtin.executeBuiltin(frame, prepareArgs(frame)); + Object result = builtin.call(frame, prepareArgs(frame)); assert result != null : "builtins cannot return 'null': " + factory.getName(); assert !(result instanceof RConnection) : "builtins cannot return connection': " + factory.getName(); visibility.execute(frame, factory.getVisibility()); @@ -224,7 +225,7 @@ public abstract class InternalNode extends OperatorNode { @Override public void voidExecute(VirtualFrame frame) { - builtin.executeBuiltin(frame, prepareArgs(frame)); + builtin.call(frame, prepareArgs(frame)); } } @@ -243,11 +244,7 @@ public abstract class InternalNode extends OperatorNode { protected Object[] prepareArgs(VirtualFrame frame) { Object[] args = new Object[arguments.length]; for (int i = 0; i < args.length; i++) { - Object value = arguments[i].execute(frame); - if (i < casts.length && casts[i] != null) { - value = casts[i].execute(value); - } - args[i] = value; + args[i] = arguments[i].execute(frame); } return args; } @@ -274,10 +271,6 @@ public abstract class InternalNode extends OperatorNode { Object value = arguments[i].execute(frame); if (i == varArgIndex) { value = forcePromises(frame, (RArgsValuesAndNames) value); - } else { - if (i < casts.length && casts[i] != null) { - value = casts[i].execute(value); - } } args[i] = value; } @@ -309,11 +302,7 @@ public abstract class InternalNode extends OperatorNode { Object[] args = new Object[factory.getSignature().getLength()]; for (int i = 0; i < args.length - 1; i++) { - Object value = arguments[i].execute(frame); - if (i < casts.length && casts[i] != null) { - value = casts[i].execute(value); - } - args[i] = value; + args[i] = arguments[i].execute(frame); } Object[] varArgs = new Object[arguments.length - (factory.getSignature().getLength() - 1)]; for (int i = 0; i < varArgs.length; i++) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java index cd1b4a44df02358d9f906a802376a1a563e9abb9..f133a299b77d3b88fc20b71b577c5d51172e2f8e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java @@ -25,17 +25,21 @@ package com.oracle.truffle.r.nodes.builtin; import java.util.concurrent.ConcurrentHashMap; import com.oracle.truffle.api.dsl.GeneratedBy; +import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineBuilder; import com.oracle.truffle.r.nodes.builtin.casts.fluent.PreinitialPhaseBuilder; import com.oracle.truffle.r.nodes.unary.CastNode; import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode; +import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.builtins.RBuiltin; public interface NodeWithArgumentCasts { default Casts getCastHolder() { - Class<?> cls = Casts.getBuiltinClass(getClass()); - Casts casts = Casts.forClass(cls); - assert casts != null || Casts.noCastsAllowed(getClass().getSuperclass()) : "No casts associated with builtin " + cls; + return getStaticCasts(getClass()); + } + + static Casts getStaticCasts(Class<?> builtinClass) { + Casts casts = Casts.getCasts(builtinClass); return casts == null ? Casts.empty : casts; } @@ -49,18 +53,34 @@ public interface NodeWithArgumentCasts { private static final Casts empty = new Casts(); protected final CastBuilder casts; + private final boolean declaresNoCasts; private Casts() { casts = new CastBuilder(); + this.declaresNoCasts = false; } public Casts(Class<? extends NodeWithArgumentCasts> cls) { - casts = new CastBuilder(cls.getAnnotation(RBuiltin.class)); castsMap.put(cls, this); + casts = new CastBuilder(cls.getAnnotation(RBuiltin.class)); + this.declaresNoCasts = false; + } + + private Casts(Class<? extends NodeWithArgumentCasts> cls, boolean declaresNoCasts) { + casts = new CastBuilder(cls.getAnnotation(RBuiltin.class)); + this.declaresNoCasts = declaresNoCasts; } public static void noCasts(Class<? extends NodeWithArgumentCasts> cls) { - castsMap.put(cls, new Casts(cls)); + castsMap.put(cls, new Casts(cls, true)); + } + + /** + * Indicates that a builtin uses the {@link Casts#noCasts(Class)} to declare that it uses no + * arguments casts although it has one or more arguments. + */ + public boolean declaresNoCasts() { + return declaresNoCasts; } public static Casts forClass(Class<?> cls) { @@ -71,6 +91,10 @@ public interface NodeWithArgumentCasts { return casts.getCasts(); } + public PipelineBuilder[] getPipelineBuilders() { + return casts.getPipelineBuilders(); + } + public PreinitialPhaseBuilder arg(String argumentName) { return casts.arg(argumentName); } @@ -83,6 +107,15 @@ public interface NodeWithArgumentCasts { return casts.arg(argumentIndex); } + public static Casts getCasts(Class<?> builtinClass) { + Class<?> cls = Casts.getBuiltinClass(builtinClass); + Casts casts = Casts.forClass(cls); + if (casts == null && !noCastsAllowed(cls)) { + throw RInternalError.shouldNotReachHere("No casts associated with builtin " + cls); + } + return casts; + } + private static boolean noCastsAllowed(Class<?> cls) { boolean res = RExternalBuiltinNode.Arg0.class.isAssignableFrom(cls) || UnaryArithmeticBuiltinNode.class.isAssignableFrom(cls) || (RBuiltinNode.class.isAssignableFrom(cls) && hasNoArguments(cls)); @@ -94,7 +127,7 @@ public interface NodeWithArgumentCasts { return a != null && a.parameterNames().length == 0; } - private static Class<?> getBuiltinClass(Class<?> cls) { + public static Class<?> getBuiltinClass(Class<?> cls) { if (cls.getAnnotation(GeneratedBy.class) != null) { return cls.getSuperclass(); } else { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinFactory.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinFactory.java index 5ef1dd975e00d8128a0f2ec26632ca5178e19a62..90e34ba0ecdbde856e17300a70ec6a40eea09bce 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinFactory.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinFactory.java @@ -22,7 +22,6 @@ */ package com.oracle.truffle.r.nodes.builtin; -import java.util.Arrays; import java.util.function.Supplier; import com.oracle.truffle.r.runtime.ArgumentsSignature; @@ -46,10 +45,4 @@ public final class RBuiltinFactory extends RBuiltinDescriptor { public Supplier<RBuiltinNode> getConstructor() { return constructor; } - - @Override - public String toString() { - return "RBuiltinFactory [name=" + getName() + ", aliases=" + Arrays.toString(getAliases()) + ", kind=" + getKind() + ", siagnature=" + getSignature() + ", nonEvaledArgs=" + - Arrays.toString(getNonEvalArgs()) + ", splitCaller=" + isSplitCaller() + ", dispatch=" + getDispatch() + ", behavior=" + getBehavior() + "]"; - } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java index 579352ce12d9b2c9b7eff4fa13c13335e7d81dfc..8defc8bd28a60914b203f7e5221086d8f380fdaa 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java @@ -22,16 +22,16 @@ */ package com.oracle.truffle.r.nodes.builtin; -import com.oracle.truffle.api.CompilerAsserts; -import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.dsl.GeneratedBy; import com.oracle.truffle.api.dsl.TypeSystemReference; -import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.r.nodes.function.FormalArguments; import com.oracle.truffle.r.nodes.function.RCallNode; +import com.oracle.truffle.r.nodes.unary.CastNode; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.ErrorContext; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor; import com.oracle.truffle.r.runtime.builtins.RBuiltinKind; @@ -39,16 +39,16 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RTypes; -import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; +import com.oracle.truffle.r.runtime.nodes.builtin.RBuiltinBaseNode; @TypeSystemReference(RTypes.class) -public abstract class RBuiltinNode extends RBaseNode implements NodeWithArgumentCasts { +public abstract class RBuiltinNode extends RBuiltinBaseNode implements NodeWithArgumentCasts { - public abstract Object executeBuiltin(VirtualFrame frame, Object... args); + public abstract Object call(VirtualFrame frame, Object... args); /** * Return the default values of the builtin's formal arguments. This is only valid for builtins @@ -60,22 +60,6 @@ public abstract class RBuiltinNode extends RBaseNode implements NodeWithArgument return EMPTY_OBJECT_ARRAY; } - static RootCallTarget createArgumentsCallTarget(RBuiltinFactory builtin) { - CompilerAsserts.neverPartOfCompilation(); - - RBuiltinNode node = builtin.getConstructor().get(); - FormalArguments formals = FormalArguments.createForBuiltin(node.getDefaultParameterValues(), builtin.getSignature()); - if (builtin.getKind() == RBuiltinKind.INTERNAL) { - assert node.getDefaultParameterValues().length == 0 : "INTERNAL builtins do not need default values"; - assert builtin.getSignature().getVarArgCount() == 0 || builtin.getSignature().getVarArgIndex() == builtin.getSignature().getLength() - 1 : "only last argument can be vararg"; - } - - FrameDescriptor frameDescriptor = new FrameDescriptor(); - RBuiltinRootNode root = new RBuiltinRootNode(builtin, node, formals, frameDescriptor, null); - FrameSlotChangeMonitor.initializeFunctionFrameDescriptor(builtin.getName(), frameDescriptor); - return Truffle.getRuntime().createCallTarget(root); - } - public static final RBuiltinNode inline(RBuiltinDescriptor factory) { // static number of arguments return ((RBuiltinFactory) factory).getConstructor().get(); @@ -122,4 +106,225 @@ public abstract class RBuiltinNode extends RBaseNode implements NodeWithArgument return (getRBuiltin() == null ? getClass().getSimpleName() : getRBuiltin().name()); } + @Override + public RBaseNode getErrorContext() { + ErrorContext context = RError.contextForBuiltin(getRBuiltin()); + return context == null ? this : context; + } + + @Children private final CastNode[] argumentCasts; + @CompilationFinal(dimensions = 1) private final Class<?>[] argumentClasses; + + protected RBuiltinNode(int argCount) { + argumentCasts = getCasts(); + argumentClasses = new Class<?>[argCount]; + } + + protected Object castArg(Object[] args, int index) { + Object value; + if (index < argumentCasts.length && argumentCasts[index] != null) { + value = argumentCasts[index].doCast(args[index]); + } else { + value = args[index]; + } + Class<?> clazz = argumentClasses[index]; + if (clazz == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + argumentClasses[index] = clazz = value.getClass(); + return value; + } else if (clazz == Object.class) { + return value; + } else if (value.getClass() == clazz) { + if (CompilerDirectives.inInterpreter()) { + return value; + } + return clazz.cast(value); + } else { + CompilerDirectives.transferToInterpreterAndInvalidate(); + argumentClasses[index] = Object.class; + return value; + } + } + + public abstract static class Arg0 extends RBuiltinNode { + + public abstract Object execute(VirtualFrame frame); + + protected Arg0() { + super(0); + } + + @Override + public final Object call(VirtualFrame frame, Object... args) { + return execute(frame); + } + } + + public abstract static class Arg1 extends RBuiltinNode { + public abstract Object execute(VirtualFrame frame, Object arg); + + protected Arg1() { + super(1); + } + + @Override + public final Object call(VirtualFrame frame, Object... args) { + return execute(frame, castArg(args, 0)); + } + } + + public abstract static class Arg2 extends RBuiltinNode { + public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2); + + protected Arg2() { + super(2); + } + + @Override + public final Object call(VirtualFrame frame, Object... args) { + return execute(frame, castArg(args, 0), castArg(args, 1)); + } + } + + public abstract static class Arg3 extends RBuiltinNode { + public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3); + + protected Arg3() { + super(3); + } + + @Override + public final Object call(VirtualFrame frame, Object... args) { + return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2)); + } + } + + public abstract static class Arg4 extends RBuiltinNode { + public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4); + + protected Arg4() { + super(4); + } + + @Override + public final Object call(VirtualFrame frame, Object... args) { + return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3)); + } + } + + public abstract static class Arg5 extends RBuiltinNode { + public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5); + + protected Arg5() { + super(5); + } + + @Override + public final Object call(VirtualFrame frame, Object... args) { + return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4)); + } + } + + public abstract static class Arg6 extends RBuiltinNode { + public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6); + + protected Arg6() { + super(6); + } + + @Override + public final Object call(VirtualFrame frame, Object... args) { + return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4), castArg(args, 5)); + } + } + + public abstract static class Arg7 extends RBuiltinNode { + + public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7); + + protected Arg7() { + super(7); + } + + @Override + public final Object call(VirtualFrame frame, Object... args) { + return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4), castArg(args, 5), castArg(args, 6)); + } + } + + public abstract static class Arg8 extends RBuiltinNode { + + public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8); + + protected Arg8() { + super(8); + } + + @Override + public final Object call(VirtualFrame frame, Object... args) { + return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4), castArg(args, 5), castArg(args, 6), castArg(args, 7)); + } + } + + public abstract static class Arg9 extends RBuiltinNode { + + public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9); + + protected Arg9() { + super(9); + } + + @Override + public final Object call(VirtualFrame frame, Object... args) { + return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4), castArg(args, 5), castArg(args, 6), castArg(args, 7), castArg(args, 8)); + } + } + + public abstract static class Arg10 extends RBuiltinNode { + + public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10); + + protected Arg10() { + super(10); + } + + @Override + public final Object call(VirtualFrame frame, Object... args) { + return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4), castArg(args, 5), castArg(args, 6), castArg(args, 7), castArg(args, 8), + castArg(args, 9)); + } + } + + public abstract static class Arg11 extends RBuiltinNode { + + public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, + Object arg11); + + protected Arg11() { + super(11); + } + + @Override + public final Object call(VirtualFrame frame, Object... args) { + return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4), castArg(args, 5), castArg(args, 6), castArg(args, 7), castArg(args, 8), + castArg(args, 9), castArg(args, 10)); + } + } + + public abstract static class Arg19 extends RBuiltinNode { + + public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10, + Object arg11, Object arg12, Object arg13, Object arg14, Object arg15, Object arg16, Object arg17, Object arg18, Object arg19); + + protected Arg19() { + super(19); + } + + @Override + public final Object call(VirtualFrame frame, Object... args) { + return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4), castArg(args, 5), castArg(args, 6), castArg(args, 7), castArg(args, 8), + castArg(args, 9), castArg(args, 10), castArg(args, 11), castArg(args, 12), castArg(args, 13), castArg(args, 14), castArg(args, 15), castArg(args, 16), castArg(args, 17), + castArg(args, 18)); + } + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java index 88652dcff593da9f9dbe5f59bcddc6c084d16c8c..32eb510cc7ad64356f927f4ade21c5daef213820 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java @@ -33,8 +33,10 @@ import com.oracle.truffle.r.nodes.access.AccessArgumentNode; import com.oracle.truffle.r.nodes.function.FormalArguments; import com.oracle.truffle.r.nodes.function.RCallNode.BuiltinCallNode; import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.builtins.FastPathFactory; +import com.oracle.truffle.r.runtime.builtins.RBuiltinKind; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; @@ -44,21 +46,31 @@ public final class RBuiltinRootNode extends RRootNode { @Children private final AccessArgumentNode[] args; @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); - private final RBuiltinNode builtin; private final RBuiltinFactory factory; - RBuiltinRootNode(RBuiltinFactory factory, RBuiltinNode builtin, FormalArguments formalArguments, FrameDescriptor frameDescriptor, FastPathFactory fastPath) { - super(formalArguments, frameDescriptor, fastPath); + RBuiltinRootNode(RBuiltinFactory factory, FrameDescriptor frameDescriptor, FastPathFactory fastPath) { + super(frameDescriptor, fastPath); this.factory = factory; - this.builtin = builtin; this.args = new AccessArgumentNode[factory.getSignature().getLength()]; } + @Override + public FormalArguments getFormalArguments() { + initialize(); + return call.getFormals(); + } + + @Override + public ArgumentsSignature getSignature() { + initialize(); + return call.getFormals().getSignature(); + } + @Override public RootCallTarget duplicateWithNewFrameDescriptor() { FrameDescriptor frameDescriptor = new FrameDescriptor(); FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("builtin", frameDescriptor); - return Truffle.getRuntime().createCallTarget(new RBuiltinRootNode(factory, (RBuiltinNode) builtin.deepCopy(), getFormalArguments(), frameDescriptor, getFastPath())); + return Truffle.getRuntime().createCallTarget(new RBuiltinRootNode(factory, frameDescriptor, getFastPath())); } @Override @@ -71,14 +83,7 @@ public final class RBuiltinRootNode extends RRootNode { public Object execute(VirtualFrame frame) { verifyEnclosingAssumptions(frame); try { - if (call == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - this.call = insert(new BuiltinCallNode(builtin, factory, getFormalArguments(), null, true)); - for (int i = 0; i < args.length; i++) { - args[i] = insert(AccessArgumentNode.create(i)); - args[i].setFormals(getFormalArguments()); - } - } + initialize(); Object[] arguments = new Object[args.length]; for (int i = 0; i < args.length; i++) { arguments[i] = args[i].execute(frame); @@ -93,8 +98,26 @@ public final class RBuiltinRootNode extends RRootNode { } } + private void initialize() { + if (call == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + RBuiltinNode builtin = factory.getConstructor().get(); + FormalArguments formalArguments = FormalArguments.createForBuiltin(builtin.getDefaultParameterValues(), factory.getSignature()); + if (factory.getKind() == RBuiltinKind.INTERNAL) { + assert builtin.getDefaultParameterValues().length == 0 : "INTERNAL builtins do not need default values"; + assert factory.getSignature().getVarArgCount() == 0 || factory.getSignature().getVarArgIndex() == factory.getSignature().getLength() - 1 : "only last argument can be vararg"; + } + call = insert(new BuiltinCallNode(builtin, factory, formalArguments, null, true)); + for (int i = 0; i < args.length; i++) { + args[i] = insert(AccessArgumentNode.create(i)); + args[i].setFormals(formalArguments); + } + } + } + public RBuiltinNode getBuiltinNode() { - return builtin; + initialize(); + return call.getBuiltin(); } @Override @@ -119,6 +142,6 @@ public final class RBuiltinRootNode extends RRootNode { @Override public String getName() { - return "RBuiltin(" + builtin + ")"; + return "RBuiltin(" + factory.getName() + ")"; } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RExternalBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RExternalBuiltinNode.java index 8f4ad0a026fe1d885d3399bd7bb9f9a425cab5de..be280fcfda2c0356acadb0f0dbe2e7d9f498638d 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RExternalBuiltinNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RExternalBuiltinNode.java @@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.builtin; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.unary.CastComplexNode; import com.oracle.truffle.r.nodes.unary.CastDoubleNode; import com.oracle.truffle.r.nodes.unary.CastDoubleNodeGen; @@ -46,9 +45,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.nodes.RBaseNode; +import com.oracle.truffle.r.runtime.nodes.builtin.RBuiltinBaseNode; @TypeSystemReference(RTypes.class) -public abstract class RExternalBuiltinNode extends RBaseNode implements NodeWithArgumentCasts { +public abstract class RExternalBuiltinNode extends RBuiltinBaseNode implements NodeWithArgumentCasts { public Object call(@SuppressWarnings("unused") VirtualFrame frame, RArgsValuesAndNames args) { return call(args); @@ -56,6 +56,11 @@ public abstract class RExternalBuiltinNode extends RBaseNode implements NodeWith protected abstract Object call(RArgsValuesAndNames args); + @Override + protected RBaseNode getErrorContext() { + return RError.NO_CALLER; + } + // TODO: these should be in the build nodes @Child private CastLogicalNode castLogical; @Child private CastIntegerNode castInt; @@ -64,8 +69,6 @@ public abstract class RExternalBuiltinNode extends RBaseNode implements NodeWith @Child private CastToVectorNode castVector; @Children private final CastNode[] argumentCasts; - protected final BranchProfile errorProfile = BranchProfile.create(); - public RExternalBuiltinNode() { this.argumentCasts = getCasts(); } @@ -75,7 +78,7 @@ public abstract class RExternalBuiltinNode extends RBaseNode implements NodeWith CompilerDirectives.transferToInterpreterAndInvalidate(); castLogical = insert(CastLogicalNodeGen.create(false, false, false)); } - return ((RAbstractLogicalVector) castLogical.execute(operand)).getDataAt(0); + return ((RAbstractLogicalVector) castLogical.doCast(operand)).getDataAt(0); } protected int castInt(RAbstractVector operand) { @@ -83,7 +86,7 @@ public abstract class RExternalBuiltinNode extends RBaseNode implements NodeWith CompilerDirectives.transferToInterpreterAndInvalidate(); castInt = insert(CastIntegerNodeGen.create(false, false, false)); } - return ((RAbstractIntVector) castInt.execute(operand)).getDataAt(0); + return ((RAbstractIntVector) castInt.doCast(operand)).getDataAt(0); } protected RAbstractDoubleVector castDouble(RAbstractVector operand) { @@ -91,7 +94,7 @@ public abstract class RExternalBuiltinNode extends RBaseNode implements NodeWith CompilerDirectives.transferToInterpreterAndInvalidate(); castDouble = insert(CastDoubleNodeGen.create(false, false, false)); } - return (RAbstractDoubleVector) castDouble.execute(operand); + return (RAbstractDoubleVector) castDouble.doCast(operand); } protected RAbstractVector castVector(Object value) { @@ -99,7 +102,7 @@ public abstract class RExternalBuiltinNode extends RBaseNode implements NodeWith CompilerDirectives.transferToInterpreterAndInvalidate(); castVector = insert(CastToVectorNodeGen.create(false)); } - return (RAbstractVector) castVector.execute(value); + return (RAbstractVector) castVector.doCast(value); } protected static String isString(Object arg) { @@ -123,12 +126,13 @@ public abstract class RExternalBuiltinNode extends RBaseNode implements NodeWith if (name.endsWith("NodeGen")) { name = name.substring(0, name.length() - 7); } + // this error always shows the .Call itself throw RError.error(this, Message.INCORRECT_NOF_ARGS, args.getLength(), expectedLength, name.toLowerCase()); } } protected Object castArg(RArgsValuesAndNames args, int index) { - return index < argumentCasts.length && argumentCasts[index] != null ? argumentCasts[index].execute(args.getArgument(index)) : args.getArgument(index); + return index < argumentCasts.length && argumentCasts[index] != null ? argumentCasts[index].doCast(args.getArgument(index)) : args.getArgument(index); } public abstract static class Arg0 extends RExternalBuiltinNode { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java index cc2264b97ca612c1b46b448bac53deb1b6c53991..c7491ac86ccd76ac703d9ced6cde723c6445fe99 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java @@ -50,12 +50,12 @@ public final class RList2EnvNode extends RBaseNode { } RStringVector names = list.getNames(); if (names == null) { - throw RError.error(this, RError.Message.LIST_NAMES_SAME_LENGTH); + throw error(RError.Message.LIST_NAMES_SAME_LENGTH); } for (int i = list.getLength() - 1; i >= 0; i--) { String name = names.getDataAt(i); if (!ignoreMissingNames && name.length() == 0) { - throw RError.error(this, RError.Message.ZERO_LENGTH_VARIABLE); + throw error(RError.Message.ZERO_LENGTH_VARIABLE); } // in case of duplicates, last element in list wins if (env.get(name) == null) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RPrecedenceBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RPrecedenceBuiltinNode.java index aa07294e9735b4add74e3389b25aa6d05b411b47..fd3d5d3106b2e593b0756a529b7b4411566c92e7 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RPrecedenceBuiltinNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RPrecedenceBuiltinNode.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 @@ -26,7 +26,7 @@ import com.oracle.truffle.r.nodes.unary.PrecedenceNode; import com.oracle.truffle.r.nodes.unary.PrecedenceNodeGen; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; -public abstract class RPrecedenceBuiltinNode extends RBuiltinNode { +public abstract class RPrecedenceBuiltinNode extends RBuiltinNode.Arg3 { @Child private PrecedenceNode precedenceNode = PrecedenceNodeGen.create(); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ExecutionPathVisitor.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ExecutionPathVisitor.java new file mode 100644 index 0000000000000000000000000000000000000000..4c163d8518f554858d58b6ade8a9d286af81981b --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ExecutionPathVisitor.java @@ -0,0 +1,98 @@ +/* + * 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.nodes.builtin.casts; + +import java.util.ArrayList; +import java.util.BitSet; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep; +import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.PipelineStepVisitor; + +public abstract class ExecutionPathVisitor<T> implements PipelineStepVisitor<T> { + + private Map<MapIfStep<?, ?>, Integer> mapIfStepStatuses; + private BitSet bs; + private int mapIfCounter; + private List<T> results = new ArrayList<>(); + + @SuppressWarnings("unchecked") + public List<T> visitPaths(PipelineStep<?, ?> firstStep, T initial) { + if (firstStep == null) { + return Collections.singletonList(initial); + } + mapIfStepStatuses = new HashMap<>(); + results.add(firstStep.acceptPipeline(this, initial)); + int n = 1 << mapIfStepStatuses.size(); + for (long i = 1; i < n; i++) { + bs = BitSet.valueOf(new long[]{i}); + T res; + try { + res = firstStep.acceptPipeline(this, initial); + } catch (PathBreakException br) { + res = (T) br.result; + } + results.add(res); + } + return results; + } + + @Override + public final T visit(MapIfStep<?, ?> step, T previous) { + boolean visitTrueBranch = bs == null ? false : bs.get(mapIfStepStatuses.get(step)); + if (bs == null) { + visitTrueBranch = false; + mapIfStepStatuses.put(step, mapIfCounter++); + } else { + visitTrueBranch = bs.get(mapIfStepStatuses.get(step)); + } + T res = visitBranch(step, previous, visitTrueBranch); + if (step.isReturns() && visitTrueBranch) { + throw new PathBreakException(res); + } else { + return res; + } + } + + protected abstract T visitBranch(MapIfStep<?, ?> step, T previous, boolean visitTrueBranch); + + @SuppressWarnings("serial") + static final class PathBreakException extends RuntimeException { + + private final Object result; + + private PathBreakException(Object result) { + this.result = result; + } + + @SuppressWarnings("sync-override") + @Override + public Throwable fillInStackTrace() { + return null; + } + } + +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java index f26904e04cb65c7a0a377940a3408b9a58bdc94b..ad1729b0ab65416d363f3ab32156920839f55275 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java @@ -40,11 +40,6 @@ public abstract class Filter<T, R extends T> { protected Filter() { } - /** - * @return true if this filter narrows the input type to a sub-type - */ - public abstract boolean isNarrowing(); - public ResultForArg resultForNull() { return ResultForArg.UNDEFINED; } @@ -53,7 +48,7 @@ public abstract class Filter<T, R extends T> { return ResultForArg.UNDEFINED; } - public abstract <D> D accept(FilterVisitor<D> visitor); + public abstract <D> D accept(FilterVisitor<D> visitor, D previous); public <S extends R> AndFilter<T, S> and(Filter<? super R, S> other) { return new AndFilter<>(this, other); @@ -68,25 +63,25 @@ public abstract class Filter<T, R extends T> { } public interface FilterVisitor<D> { - D visit(TypeFilter<?, ?> filter); + D visit(TypeFilter<?, ?> filter, D previous); - D visit(RTypeFilter<?> filter); + D visit(RTypeFilter<?> filter, D previous); - D visit(CompareFilter<?> filter); + D visit(CompareFilter<?> filter, D previous); - D visit(AndFilter<?, ?> filter); + D visit(AndFilter<?, ?> filter, D previous); - D visit(OrFilter<?> filter); + D visit(OrFilter<?> filter, D previous); - D visit(NotFilter<?> filter); + D visit(NotFilter<?> filter, D previous); - D visit(MatrixFilter<?> filter); + D visit(MatrixFilter<?> filter, D previous); - D visit(DoubleFilter filter); + D visit(DoubleFilter filter, D previous); - D visit(NullFilter filter); + D visit(NullFilter filter, D previous); - D visit(MissingFilter filter); + D visit(MissingFilter filter, D previous); } /** @@ -134,11 +129,6 @@ public abstract class Filter<T, R extends T> { return extraCondition; } - @Override - public boolean isNarrowing() { - return true; - } - @SuppressWarnings("unchecked") public ArgumentFilter<Object, Object> getInstanceOfLambda() { final ArgumentFilter<Object, Object> instanceOfLambda; @@ -163,8 +153,8 @@ public abstract class Filter<T, R extends T> { } @Override - public <D> D accept(FilterVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(FilterVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } @Override @@ -195,13 +185,8 @@ public abstract class Filter<T, R extends T> { } @Override - public boolean isNarrowing() { - return true; - } - - @Override - public <D> D accept(FilterVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(FilterVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } @Override @@ -223,13 +208,8 @@ public abstract class Filter<T, R extends T> { } @Override - public boolean isNarrowing() { - return true; - } - - @Override - public <D> D accept(FilterVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(FilterVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } @Override @@ -251,13 +231,8 @@ public abstract class Filter<T, R extends T> { } @Override - public boolean isNarrowing() { - return true; - } - - @Override - public <D> D accept(FilterVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(FilterVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } @Override @@ -278,21 +253,21 @@ public abstract class Filter<T, R extends T> { public static final class CompareFilter<T> extends Filter<T, T> { public interface Subject { - <D> D accept(SubjectVisitor<D> visitor, byte operation); + <D> D accept(SubjectVisitor<D> visitor, byte operation, D previous); } public interface SubjectVisitor<D> { - D visit(ScalarValue scalarValue, byte operation); + D visit(ScalarValue scalarValue, byte operation, D previous); - D visit(NATest naTest, byte operation); + D visit(NATest naTest, byte operation, D previous); - D visit(StringLength stringLength, byte operation); + D visit(StringLength stringLength, byte operation, D previous); - D visit(VectorSize vectorSize, byte operation); + D visit(VectorSize vectorSize, byte operation, D previous); - D visit(ElementAt elementAt, byte operation); + D visit(ElementAt elementAt, byte operation, D previous); - D visit(Dim dim, byte operation); + D visit(Dim dim, byte operation, D previous); } public static final class ScalarValue implements Subject { @@ -305,8 +280,8 @@ public abstract class Filter<T, R extends T> { } @Override - public <D> D accept(SubjectVisitor<D> visitor, byte operation) { - return visitor.visit(this, operation); + public <D> D accept(SubjectVisitor<D> visitor, byte operation, D previous) { + return visitor.visit(this, operation, previous); } } @@ -318,8 +293,8 @@ public abstract class Filter<T, R extends T> { } @Override - public <D> D accept(SubjectVisitor<D> visitor, byte operation) { - return visitor.visit(this, operation); + public <D> D accept(SubjectVisitor<D> visitor, byte operation, D previous) { + return visitor.visit(this, operation, previous); } } @@ -331,8 +306,8 @@ public abstract class Filter<T, R extends T> { } @Override - public <D> D accept(SubjectVisitor<D> visitor, byte operation) { - return visitor.visit(this, operation); + public <D> D accept(SubjectVisitor<D> visitor, byte operation, D previous) { + return visitor.visit(this, operation, previous); } } @@ -344,8 +319,8 @@ public abstract class Filter<T, R extends T> { } @Override - public <D> D accept(SubjectVisitor<D> visitor, byte operation) { - return visitor.visit(this, operation); + public <D> D accept(SubjectVisitor<D> visitor, byte operation, D previous) { + return visitor.visit(this, operation, previous); } } @@ -361,8 +336,8 @@ public abstract class Filter<T, R extends T> { } @Override - public <D> D accept(SubjectVisitor<D> visitor, byte operation) { - return visitor.visit(this, operation); + public <D> D accept(SubjectVisitor<D> visitor, byte operation, D previous) { + return visitor.visit(this, operation, previous); } } @@ -376,8 +351,8 @@ public abstract class Filter<T, R extends T> { } @Override - public <D> D accept(SubjectVisitor<D> visitor, byte operation) { - return visitor.visit(this, operation); + public <D> D accept(SubjectVisitor<D> visitor, byte operation, D previous) { + return visitor.visit(this, operation, previous); } } @@ -386,22 +361,17 @@ public abstract class Filter<T, R extends T> { public static final byte LT = 2; public static final byte GE = 3; public static final byte LE = 4; - public static final byte SAME = 5; + public static final byte STRING_EQ = 5; private final byte operation; private final Subject subject; public CompareFilter(byte operation, Subject subject) { - assert operation <= SAME : "wrong operation value"; + assert operation <= STRING_EQ : "wrong operation value"; this.operation = operation; this.subject = subject; } - @Override - public boolean isNarrowing() { - return false; - } - public Subject getSubject() { return subject; } @@ -411,8 +381,8 @@ public abstract class Filter<T, R extends T> { } @Override - public <D> D accept(FilterVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(FilterVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } @Override @@ -430,22 +400,22 @@ public abstract class Filter<T, R extends T> { private static final MatrixFilter<RAbstractVector> IS_MATRIX = new MatrixFilter<RAbstractVector>() { @Override - public <D> D acceptOperation(OperationVisitor<D> visitor) { - return visitor.visitIsMatrix(); + public <D> D acceptOperation(OperationVisitor<D> visitor, D previous) { + return visitor.visitIsMatrix(previous); } }; private static final MatrixFilter<RAbstractVector> IS_SQUARE_MATRIX = new MatrixFilter<RAbstractVector>() { @Override - public <D> D acceptOperation(OperationVisitor<D> visitor) { - return visitor.visitIsSquareMatrix(); + public <D> D acceptOperation(OperationVisitor<D> visitor, D previous) { + return visitor.visitIsSquareMatrix(previous); } }; public interface OperationVisitor<D> { - D visitIsMatrix(); + D visitIsMatrix(D previous); - D visitIsSquareMatrix(); + D visitIsSquareMatrix(D previous); } @SuppressWarnings("unchecked") @@ -461,16 +431,11 @@ public abstract class Filter<T, R extends T> { private MatrixFilter() { } - @Override - public boolean isNarrowing() { - return false; - } - - public abstract <D> D acceptOperation(OperationVisitor<D> visitor); + public abstract <D> D acceptOperation(OperationVisitor<D> visitor, D previous); @Override - public <D> D accept(FilterVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(FilterVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } } @@ -478,38 +443,33 @@ public abstract class Filter<T, R extends T> { public static final DoubleFilter IS_FINITE = new DoubleFilter() { @Override - public <D> D acceptOperation(OperationVisitor<D> visitor) { - return visitor.visitIsFinite(); + public <D> D acceptOperation(OperationVisitor<D> visitor, D previous) { + return visitor.visitIsFinite(previous); } }; public static final DoubleFilter IS_FRACTIONAL = new DoubleFilter() { @Override - public <D> D acceptOperation(OperationVisitor<D> visitor) { - return visitor.visitIsFractional(); + public <D> D acceptOperation(OperationVisitor<D> visitor, D previous) { + return visitor.visitIsFractional(previous); } }; public interface OperationVisitor<D> { - D visitIsFinite(); + D visitIsFinite(D previous); - D visitIsFractional(); + D visitIsFractional(D previous); } private DoubleFilter() { } - @Override - public boolean isNarrowing() { - return false; - } - - public abstract <D> D acceptOperation(OperationVisitor<D> visitor); + public abstract <D> D acceptOperation(OperationVisitor<D> visitor, D previous); @Override - public <D> D accept(FilterVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(FilterVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } } @@ -522,11 +482,6 @@ public abstract class Filter<T, R extends T> { this.right = right; } - @Override - public boolean isNarrowing() { - return left.isNarrowing() || right.isNarrowing(); - } - public Filter<?, ?> getLeft() { return left; } @@ -536,8 +491,8 @@ public abstract class Filter<T, R extends T> { } @Override - public <D> D accept(FilterVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(FilterVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } @Override @@ -560,11 +515,6 @@ public abstract class Filter<T, R extends T> { this.right = right; } - @Override - public boolean isNarrowing() { - return false; - } - public Filter<?, ?> getLeft() { return left; } @@ -574,8 +524,8 @@ public abstract class Filter<T, R extends T> { } @Override - public <D> D accept(FilterVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(FilterVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } @Override @@ -596,18 +546,13 @@ public abstract class Filter<T, R extends T> { this.filter = filter; } - @Override - public boolean isNarrowing() { - return false; - } - public Filter<?, ?> getFilter() { return filter; } @Override - public <D> D accept(FilterVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(FilterVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } @Override @@ -629,7 +574,7 @@ public abstract class Filter<T, R extends T> { * The <code>FALSE</code>, resp. <code>TRUE</code>, indicates that the filter will always return * <code>false</code>, resp. <code>true</code>, for the given input value. * <p> - * The <code>UNSUPPORTED</code> indicates that the the given input value is out of the filter's + * The <code>UNDEFINED</code> indicates that the the given input value is out of the filter's * domain. * * @see Filter#resultForNull() diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Mapper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Mapper.java index c47c8dd1797ff1299d932daaba0015aa57657184..1f0aa72e47d9ddbc2540405c99f9fdd68a8d906c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Mapper.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Mapper.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 @@ -29,16 +29,16 @@ import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep; */ public abstract class Mapper<T, R> { - public abstract <D> D accept(MapperVisitor<D> visitor); + public abstract <D> D accept(MapperVisitor<D> visitor, D previous); public interface MapperVisitor<D> { - D visit(MapToValue<?, ?> mapper); + D visit(MapToValue<?, ?> mapper, D previous); - D visit(MapByteToBoolean mapper); + D visit(MapByteToBoolean mapper, D previous); - D visit(MapDoubleToInt mapper); + D visit(MapDoubleToInt mapper, D previous); - D visit(MapToCharAt mapper); + D visit(MapToCharAt mapper, D previous); } public static final class MapToValue<T, R> extends Mapper<T, R> { @@ -53,22 +53,21 @@ public abstract class Mapper<T, R> { } @Override - public <D> D accept(MapperVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(MapperVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } } public static final class MapByteToBoolean extends Mapper<Byte, Boolean> { + public final boolean naReplacement; - public static final MapByteToBoolean INSTANCE = new MapByteToBoolean(); - - private MapByteToBoolean() { - + public MapByteToBoolean(boolean naReplacement) { + this.naReplacement = naReplacement; } @Override - public <D> D accept(MapperVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(MapperVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } } @@ -80,8 +79,8 @@ public abstract class Mapper<T, R> { } @Override - public <D> D accept(MapperVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(MapperVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } } @@ -103,8 +102,8 @@ public abstract class Mapper<T, R> { } @Override - public <D> D accept(MapperVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(MapperVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java index d82b22e6c46a4d0faf36a3a5bd674f8fe144f4a5..5d875a64a45c42ad240b73e8811319f681841070 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.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 @@ -22,28 +22,21 @@ */ package com.oracle.truffle.r.nodes.builtin.casts; -import com.oracle.truffle.api.CompilerDirectives.ValueType; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; +import com.oracle.truffle.r.runtime.RInternalError; /** * Value type that holds data necessary for error/warning message from a cast pipeline. */ -@ValueType public final class MessageData { - private final RBaseNode callObj; private final RError.Message message; private final Object[] messageArgs; - public MessageData(RBaseNode callObj, Message message, Object... messageArgs) { - this.callObj = callObj; + public MessageData(Message message, Object... messageArgs) { this.message = message; this.messageArgs = messageArgs; - } - - public RBaseNode getCallObj() { - return callObj; + assert message != null; } public Message getMessage() { @@ -54,19 +47,15 @@ public final class MessageData { return messageArgs; } - public MessageData fixCallObj(RBaseNode callObjFix) { - if (callObj == null) { - return new MessageData(callObjFix, message, messageArgs); - } else { - return this; - } - } - /** * Helper method for operation that is often performed with {@link MessageData}. */ - public static MessageData getFirstNonNull(MessageData first, MessageData second, MessageData third) { - assert third != null : "at least the last one must not be null"; - return first != null && first.getMessage() != null ? first : second != null && second.getMessage() != null ? second : third; + public static MessageData getFirstNonNull(MessageData... messages) { + for (MessageData message : messages) { + if (message != null) { + return message; + } + } + throw RInternalError.shouldNotReachHere("at least the last message must not be null"); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineConfig.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineConfig.java index 42146741e4b0416856857914b0f68e07e57005be..607f55a25861a11743c224f8c488bb4f2dc0e505 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineConfig.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineConfig.java @@ -22,14 +22,8 @@ */ package com.oracle.truffle.r.nodes.builtin.casts; -import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode.ArgumentFilterFactory; -import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode.ArgumentFilterFactoryImpl; -import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode.ArgumentMapperFactory; -import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode.ArgumentMapperFactoryImpl; import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineConfigBuilder; import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RNull; /** * Immutable class with configuration of the pipeline. Create using {@link PipelineConfigBuilder}. @@ -38,29 +32,15 @@ import com.oracle.truffle.r.runtime.data.RNull; * warning if RNull/RMissing occurs. */ public class PipelineConfig { - private static ArgumentFilterFactory filterFactory = ArgumentFilterFactoryImpl.INSTANCE; - private static ArgumentMapperFactory mapperFactory = ArgumentMapperFactoryImpl.INSTANCE; - private final String argumentName; private final MessageData defaultError; private final MessageData defaultWarning; - private final Mapper<? super RMissing, ?> missingMapper; - private final Mapper<? super RNull, ?> nullMapper; - private final MessageData missingMsg; - private final MessageData nullMsg; private boolean valueForwarding; - public PipelineConfig(String argumentName, MessageData defaultError, MessageData defaultWarning, Mapper<? super RMissing, ?> missingMapper, Mapper<? super RNull, ?> nullMapper, - boolean valueForwarding, - MessageData missingMsg, - MessageData nullMsg) { + public PipelineConfig(String argumentName, MessageData defaultError, MessageData defaultWarning, boolean valueForwarding) { this.defaultError = defaultError; this.defaultWarning = defaultWarning; - this.missingMapper = missingMapper; - this.nullMapper = nullMapper; this.valueForwarding = valueForwarding; - this.missingMsg = missingMsg; - this.nullMsg = nullMsg; this.argumentName = argumentName; } @@ -69,7 +49,7 @@ public class PipelineConfig { * time being this is not configurable. */ public MessageData getDefaultDefaultMessage() { - return new MessageData(null, RError.Message.INVALID_ARGUMENT, argumentName); + return new MessageData(RError.Message.INVALID_ARGUMENT, argumentName); } public MessageData getDefaultError() { @@ -80,39 +60,7 @@ public class PipelineConfig { return defaultWarning; } - public Mapper<? super RMissing, ?> getMissingMapper() { - return missingMapper; - } - - public Mapper<? super RNull, ?> getNullMapper() { - return nullMapper; - } - - public MessageData getMissingMessage() { - return missingMsg; - } - - public MessageData getNullMessage() { - return nullMsg; - } - public boolean getValueForwarding() { return valueForwarding; } - - public static ArgumentFilterFactory getFilterFactory() { - return filterFactory; - } - - public static ArgumentMapperFactory getMapperFactory() { - return mapperFactory; - } - - public static void setFilterFactory(ArgumentFilterFactory ff) { - filterFactory = ff; - } - - public static void setMapperFactory(ArgumentMapperFactory mf) { - mapperFactory = mf; - } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java index e6bbe5e5a4dd973d1f44c9005321aa054bad2640..7f4776692ec9714a69e551a85df015bd8896763d 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.builtin.casts; +import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -48,78 +49,34 @@ public abstract class PipelineStep<T, R> { return this; } - public abstract <D> D accept(PipelineStepVisitor<D> visitor); + public abstract <D> D accept(PipelineStepVisitor<D> visitor, D previous); - public <D> D acceptPipeline(PipelineStepVisitor<D> visitor) { + public <D> D acceptPipeline(PipelineStepVisitor<D> visitor, D initial) { PipelineStep<?, ?> curStep = this; - D result = null; + D result = initial; while (curStep != null) { - result = curStep.accept(visitor); + result = curStep.accept(visitor, result); curStep = curStep.getNext(); } return result; } public interface PipelineStepVisitor<T> { - T visit(FindFirstStep<?, ?> step); + T visit(FindFirstStep<?, ?> step, T previous); - T visit(CoercionStep<?, ?> step); + T visit(CoercionStep<?, ?> step, T previous); - T visit(MapStep<?, ?> step); + T visit(MapStep<?, ?> step, T previous); - T visit(MapIfStep<?, ?> step); + T visit(MapIfStep<?, ?> step, T previous); - T visit(FilterStep<?, ?> step); + T visit(FilterStep<?, ?> step, T previous); - T visit(NotNAStep<?> step); + T visit(NotNAStep<?> step, T previous); - T visit(DefaultErrorStep<?> step); + T visit(BoxPrimitiveStep<?> step, T previous); - T visit(DefaultWarningStep<?> step); - - T visit(BoxPrimitiveStep<?> step); - - T visit(AttributableCoercionStep<?> step); - } - - /** - * Changes the current default error, which is used by steps/filters that do not have error - * message set explicitly. - */ - public abstract static class DefaultMessageStep<T> extends PipelineStep<T, T> { - private final MessageData defaultMessage; - - public DefaultMessageStep(MessageData defaultMessage) { - this.defaultMessage = defaultMessage; - } - - public MessageData getDefaultMessage() { - return defaultMessage; - } - } - - public static final class DefaultErrorStep<T> extends DefaultMessageStep<T> { - - public DefaultErrorStep(MessageData defaultMessage) { - super(defaultMessage); - } - - @Override - public <D> D accept(PipelineStepVisitor<D> visitor) { - return visitor.visit(this); - } - } - - public static final class DefaultWarningStep<T> extends DefaultMessageStep<T> { - - public DefaultWarningStep(MessageData defaultMessage) { - super(defaultMessage); - } - - @Override - public <D> D accept(PipelineStepVisitor<D> visitor) { - return visitor.visit(this); - } + T visit(AttributableCoercionStep<?> step, T previous); } /** @@ -127,8 +84,8 @@ public abstract class PipelineStep<T, R> { */ public static final class BoxPrimitiveStep<T> extends PipelineStep<T, T> { @Override - public <D> D accept(PipelineStepVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(PipelineStepVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } } @@ -142,6 +99,7 @@ public abstract class PipelineStep<T, R> { private final Object replacement; public NotNAStep(Object replacement, MessageData message) { + assert !(replacement instanceof RBaseNode || replacement instanceof RError.Message); this.replacement = replacement; this.message = message; } @@ -155,8 +113,8 @@ public abstract class PipelineStep<T, R> { } @Override - public <D> D accept(PipelineStepVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(PipelineStepVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } } @@ -165,8 +123,8 @@ public abstract class PipelineStep<T, R> { * the vector is empty, the message is used as a warning. If only default value is provided, * then if the vector is empty, the default value is returned without any warning. If the * default value is not provided, then error is raised if the vector is empty, the error message - * chosen in the following order: provided message, explicitly set default error message using - * {@link PipelineStep.DefaultErrorStep}, default find first message. + * chosen in the following order: provided message, explicitly set default error message, + * default find first message. */ public static final class FindFirstStep<V, E> extends PipelineStep<V, E> { private final MessageData error; @@ -192,8 +150,8 @@ public abstract class PipelineStep<T, R> { } @Override - public <D> D accept(PipelineStepVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(PipelineStepVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } } @@ -207,7 +165,6 @@ public abstract class PipelineStep<T, R> { public final boolean preserveNames; public final boolean preserveDimensions; public final boolean preserveAttributes; - public final RBaseNode messageCallObj; /** * Whether RNull/RMissing should be preserved, or converted to an empty list. @@ -220,34 +177,29 @@ public abstract class PipelineStep<T, R> { public final boolean vectorCoercion; public CoercionStep(RType type, boolean vectorCoercion) { - this(type, vectorCoercion, false, false, false, true, null); + this(type, vectorCoercion, false, false, false, true); } public CoercionStep(RType type, boolean vectorCoercion, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - this(type, vectorCoercion, preserveNames, preserveDimensions, preserveAttributes, true, null); + this(type, vectorCoercion, preserveNames, preserveDimensions, preserveAttributes, true); } - public CoercionStep(RType type, boolean vectorCoercion, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean preserveNonVector, RBaseNode messageCallObj) { + public CoercionStep(RType type, boolean vectorCoercion, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean preserveNonVector) { this.type = type; this.vectorCoercion = vectorCoercion; this.preserveNames = preserveNames; this.preserveAttributes = preserveAttributes; this.preserveDimensions = preserveDimensions; this.preserveNonVector = preserveNonVector; - this.messageCallObj = messageCallObj; } public RType getType() { return type; } - public RBaseNode getMessageCallObj() { - return messageCallObj; - } - @Override - public <D> D accept(PipelineStepVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(PipelineStepVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } } @@ -266,8 +218,8 @@ public abstract class PipelineStep<T, R> { } @Override - public <D> D accept(PipelineStepVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(PipelineStepVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } } @@ -283,8 +235,8 @@ public abstract class PipelineStep<T, R> { } @Override - public <D> D accept(PipelineStepVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(PipelineStepVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } } @@ -321,8 +273,15 @@ public abstract class PipelineStep<T, R> { } @Override - public <D> D accept(PipelineStepVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(PipelineStepVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); + } + + public MapIfStep<T, R> withoutReturns() { + if (!returns) { + return this; + } + return new MapIfStep<>(filter, trueBranch, falseBranch, false); } } @@ -353,8 +312,8 @@ public abstract class PipelineStep<T, R> { } @Override - public <D> D accept(PipelineStepVisitor<D> visitor) { - return visitor.visit(this); + public <D> D accept(PipelineStepVisitor<D> visitor, D previous) { + return visitor.visit(this, previous); } } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java index 09f6591a27fa2cbd11199422f7f26241eca7043a..79aa7369fffad8721bea07bc47382e7d6ceeecda 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java @@ -22,9 +22,9 @@ */ package com.oracle.truffle.r.nodes.builtin.casts; -import java.util.Optional; import java.util.function.Supplier; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode; import com.oracle.truffle.r.nodes.builtin.ArgumentFilter; import com.oracle.truffle.r.nodes.builtin.ArgumentFilter.ArgumentTypeFilter; @@ -56,8 +56,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapperVisitor; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.AttributableCoercionStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.BoxPrimitiveStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep; -import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultErrorStep; -import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultWarningStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep; @@ -65,11 +63,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.NotNAStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.PipelineStepVisitor; import com.oracle.truffle.r.nodes.builtin.casts.analysis.ForwardingAnalysisResult; -import com.oracle.truffle.r.nodes.unary.BypassNode; -import com.oracle.truffle.r.nodes.unary.BypassNodeGen.BypassDoubleNodeGen; -import com.oracle.truffle.r.nodes.unary.BypassNodeGen.BypassIntegerNodeGen; -import com.oracle.truffle.r.nodes.unary.BypassNodeGen.BypassLogicalMapToBooleanNodeGen; -import com.oracle.truffle.r.nodes.unary.BypassNodeGen.BypassStringNodeGen; import com.oracle.truffle.r.nodes.unary.CastComplexNodeGen; import com.oracle.truffle.r.nodes.unary.CastDoubleBaseNodeGen; import com.oracle.truffle.r.nodes.unary.CastDoubleNodeGen; @@ -113,30 +106,24 @@ public final class PipelineToCastNode { // nop: static class } - public static CastNode convert(PipelineConfig config, PipelineStep<?, ?> firstStep, Optional<ForwardingAnalysisResult> fwdAnalysisResult) { - return convert(config, firstStep, PipelineConfig.getFilterFactory(), PipelineConfig.getMapperFactory(), fwdAnalysisResult); - } - - public static CastNode convert(PipelineConfig config, PipelineStep<?, ?> firstStep, ArgumentFilterFactory filterFactory, ArgumentMapperFactory mapperFactory, - Optional<ForwardingAnalysisResult> fwdAnalysisResult) { - if (firstStep == null) { - return BypassNode.create(config, null, mapperFactory, null); + public static CastNode convert(PipelineConfig config, PipelineStep<?, ?> firstStepIn, ForwardingAnalysisResult fwdAnalysisResult) { + if (firstStepIn == null) { + return null; } - Supplier<CastNode> originalPipelineFactory = () -> { - CastNodeFactory nodeFactory = new CastNodeFactory(filterFactory, mapperFactory, config.getDefaultDefaultMessage()); - SinglePrimitiveOptimization singleOptVisitor = new SinglePrimitiveOptimization(nodeFactory); - CastNode headNode = convert(firstStep, singleOptVisitor); - return singleOptVisitor.createBypassNode(config, headNode, mapperFactory); - }; + // if the pipeline is only single return, we change it to map to avoid needing to catch + // the PipelineReturnException, otherwise the exception is caught by ChainedCastNode + boolean singleMapStep = firstStepIn.getNext() == null && firstStepIn instanceof MapIfStep; + PipelineStep<?, ?> firstStep = singleMapStep ? ((MapIfStep<?, ?>) firstStepIn).withoutReturns() : firstStepIn; + + Supplier<CastNode> originalPipelineFactory = () -> convert(firstStep, new CastNodeFactory(config.getDefaultError(), config.getDefaultWarning(), config.getDefaultDefaultMessage())); if (!config.getValueForwarding()) { return originalPipelineFactory.get(); } - ForwardingAnalysisResult fwdRes = fwdAnalysisResult.get(); - if (fwdRes != null && fwdRes.isAnythingForwarded()) { - return ValueForwardingNodeGen.create(fwdRes, originalPipelineFactory); + if (fwdAnalysisResult.isAnythingForwarded()) { + return ValueForwardingNodeGen.create(fwdAnalysisResult, originalPipelineFactory); } else { return originalPipelineFactory.get(); } @@ -153,13 +140,13 @@ public final class PipelineToCastNode { CastNode prevCastNode = null; PipelineStep<?, ?> currCastStep = firstStep; while (currCastStep != null) { - CastNode node = currCastStep.accept(nodeFactory); + CastNode node = currCastStep.accept(nodeFactory, prevCastNode); if (node != null) { if (prevCastNode == null) { prevCastNode = node; } else { CastNode finalPrevCastNode = prevCastNode; - prevCastNode = new ChainedCastNode(() -> finalPrevCastNode, () -> node); + prevCastNode = new ChainedCastNode(finalPrevCastNode, node, currCastStep.getNext() == null); } } @@ -168,208 +155,25 @@ public final class PipelineToCastNode { return prevCastNode; } - /** - * Visitor that is capable of recognizing patterns that permit to bypass single primitive value - * directly to any casts after find first step or directly to the built-in if there is nothing - * after find first step. - */ - private static final class SinglePrimitiveOptimization implements PipelineStepVisitor<CastNode> { - // Any destructive step or step we cannot analyze changes this to false - private boolean canBeOptimized = true; - // Any coercion or check step initialize this or check the existing value, if it does not - // match -> canBeOptimized = false - private RType targetType = null; - // We remember this step so that we can construct another copy of its cast node - private FindFirstStep<?, ?> findFirstStep = null; - private final PipelineStepVisitor<CastNode> inner; - - private SinglePrimitiveOptimization(PipelineStepVisitor<CastNode> inner) { - this.inner = inner; - } - - /** - * Creates {@link BypassNode} if there is no optimization opportunity, or creates more - * specialized child class if the cast pipeline follows the required pattern. - */ - public CastNode createBypassNode(PipelineConfig pipelineConfig, CastNode wrappedHead, ArgumentMapperFactory mapperFactory) { - if (canBeOptimized && findFirstStep != null) { - if (targetType == RType.Integer) { - return BypassIntegerNodeGen.create(pipelineConfig, wrappedHead, mapperFactory, getFindFirstWithDefault(), getAfterFindFirstNode()); - } else if (targetType == RType.Double) { - return BypassDoubleNodeGen.create(pipelineConfig, wrappedHead, mapperFactory, getFindFirstWithDefault(), getAfterFindFirstNode()); - } else if (targetType == RType.Logical && isNextMapToBoolean(findFirstStep)) { - return BypassLogicalMapToBooleanNodeGen.create(pipelineConfig, wrappedHead, mapperFactory, getFindFirstWithDefault(), getAfterFindFirstNode()); - } else if (targetType == RType.Character) { - return BypassStringNodeGen.create(pipelineConfig, wrappedHead, mapperFactory, getFindFirstWithDefault(), getAfterFindFirstNode()); - } - } - return BypassNode.create(pipelineConfig, wrappedHead, mapperFactory, getFindFirstWithDefault()); - } - - @Override - public CastNode visit(FindFirstStep<?, ?> step) { - assert !canBeOptimized || targetType != null : "There must be a coercion step before find first"; - findFirstStep = step; - return inner.visit(step); - } - - @Override - public CastNode visit(CoercionStep<?, ?> step) { - canBeOptimized(step.type); - return inner.visit(step); - } - - @Override - public CastNode visit(MapStep<?, ?> step) { - cannotBeOptimizedBeforeFindFirst(); - return inner.visit(step); - } - - @Override - public CastNode visit(MapIfStep<?, ?> step) { - cannotBeOptimizedBeforeFindFirst(); - return inner.visit(step); - } - - @Override - public CastNode visit(FilterStep<?, ?> step) { - targetType = checkFilter(step.getFilter()); - if (targetType == null) { - canBeOptimized = false; - } - return inner.visit(step); - } - - @Override - public CastNode visit(NotNAStep<?> step) { - // TODO: we can remember that we saw not NA and do this check in the BypassNode - canBeOptimized = false; - return inner.visit(step); - } - - @Override - public CastNode visit(DefaultErrorStep<?> step) { - return inner.visit(step); - } - - @Override - public CastNode visit(DefaultWarningStep<?> step) { - return inner.visit(step); - } - - @Override - public CastNode visit(BoxPrimitiveStep<?> step) { - canBeOptimized = false; - return inner.visit(step); - } - - @Override - public CastNode visit(AttributableCoercionStep<?> step) { - cannotBeOptimizedBeforeFindFirst(); - return inner.visit(step); - } - - private void cannotBeOptimizedBeforeFindFirst() { - if (findFirstStep == null) { - canBeOptimized = false; - } - } - - private void canBeOptimized(RType newType) { - if (targetType == null) { - targetType = newType; - } else if (targetType != newType) { - canBeOptimized = false; - } - } - - /** - * Returns null if the filter does not conform to expected type or does not produce some - * concrete type if there is no expected type. - */ - private RType checkFilter(Filter<?, ?> filter) { - if (filter instanceof RTypeFilter) { - RType type = ((RTypeFilter<?>) filter).getType(); - if (targetType == null) { - return type; - } - return type == targetType ? type : null; - } else if (filter instanceof OrFilter) { - OrFilter<?> or = (OrFilter<?>) filter; - RType leftType = checkFilter(or.getLeft()); - if (targetType == null) { - return leftType; - } - RType rightType = checkFilter(or.getRight()); - return rightType == targetType || leftType == targetType ? targetType : null; - } - return null; - } - - private CastNode getFindFirstWithDefault() { - if (findFirstStep != null && findFirstStep.getDefaultValue() != null) { - return convert(findFirstStep, inner); - } - return null; - } - - private CastNode getAfterFindFirstNode() { - if (findFirstStep.getNext() != null) { - return convert(findFirstStep.getNext(), inner); - } - return null; - } - - private static boolean isNextMapToBoolean(FindFirstStep<?, ?> findFirst) { - PipelineStep<?, ?> next = findFirst.getNext(); - return next != null && next instanceof MapStep && ((MapStep<?, ?>) next).getMapper() instanceof MapByteToBoolean; - } - } - private static final class CastNodeFactory implements PipelineStepVisitor<CastNode> { - private final ArgumentFilterFactory filterFactory; - private final ArgumentMapperFactory mapperFactory; private boolean boxPrimitives = false; - /** - * Should be used when {@link #defaultError} or {@link #defaultWarning} are not explicitly - * set by visiting {@link DefaultErrorStep}. - */ - private final MessageData defaultMessage; + private final MessageData defaultError; + private final MessageData defaultWarning; - /** - * Use {@link #getDefaultErrorIfNull} and {@link #getDefaultWarningIfNull} to always get a - * non-null message - they supply {@link #defaultMessage} if there is no explicitly set. - */ - private MessageData defaultError; - private MessageData defaultWarning; - - CastNodeFactory(ArgumentFilterFactory filterFactory, ArgumentMapperFactory mapperFactory, MessageData defaultMessage) { + CastNodeFactory(MessageData defaultError, MessageData defaultWarning, MessageData defaultMessage) { assert defaultMessage != null : "defaultMessage is null"; - this.filterFactory = filterFactory; - this.mapperFactory = mapperFactory; - this.defaultMessage = defaultMessage; - } - - @Override - public CastNode visit(DefaultErrorStep<?> step) { - defaultError = step.getDefaultMessage(); - return null; + this.defaultError = MessageData.getFirstNonNull(defaultError, defaultMessage); + this.defaultWarning = MessageData.getFirstNonNull(defaultWarning, defaultMessage); } @Override - public CastNode visit(DefaultWarningStep<?> step) { - defaultWarning = step.getDefaultMessage(); - return null; - } - - @Override - public CastNode visit(BoxPrimitiveStep<?> step) { + public CastNode visit(BoxPrimitiveStep<?> step, CastNode previous) { return BoxPrimitiveNode.create(); } @Override - public CastNode visit(FindFirstStep<?, ?> step) { + public CastNode visit(FindFirstStep<?, ?> step, CastNode previous) { boxPrimitives = false; // See FindFirstStep documentation on how it should be interpreted @@ -377,62 +181,63 @@ public final class PipelineToCastNode { MessageData msg = step.getError(); if (msg == null) { // Note: intentional direct use of defaultError - msg = defaultError != null ? defaultError : new MessageData(null, RError.Message.LENGTH_ZERO); + msg = defaultError != null ? defaultError : new MessageData(RError.Message.LENGTH_ZERO); } - return FindFirstNodeGen.create(step.getElementClass(), msg.getCallObj(), msg.getMessage(), msg.getMessageArgs(), step.getDefaultValue()); + return FindFirstNodeGen.create(step.getElementClass(), msg, step.getDefaultValue()); } else { MessageData warning = step.getError(); if (warning == null) { return FindFirstNodeGen.create(step.getElementClass(), step.getDefaultValue()); } else { - return FindFirstNodeGen.create(step.getElementClass(), warning.getCallObj(), warning.getMessage(), warning.getMessageArgs(), step.getDefaultValue()); + return FindFirstNodeGen.create(step.getElementClass(), warning, step.getDefaultValue()); } } } @Override - public CastNode visit(FilterStep<?, ?> step) { - ArgumentFilter<?, ?> filter = filterFactory.createFilter(step.getFilter()); + public CastNode visit(FilterStep<?, ?> step, CastNode previous) { + @SuppressWarnings("unchecked") + ArgumentFilter<Object, Object> filter = (ArgumentFilter<Object, Object>) ArgumentFilterFactoryImpl.INSTANCE.createFilter(step.getFilter()); MessageData msg = getDefaultIfNull(step.getMessage(), step.isWarning()); - return FilterNode.create(filter, step.isWarning(), msg.getCallObj(), msg.getMessage(), msg.getMessageArgs(), boxPrimitives, ResultForArg.TRUE.equals(step.getFilter().resultForNull()), - ResultForArg.TRUE.equals(step.getFilter().resultForMissing())); + return FilterNode.create(filter, step.isWarning(), msg, boxPrimitives, step.getFilter().resultForNull() == ResultForArg.TRUE, + step.getFilter().resultForMissing() == ResultForArg.TRUE); } @Override - public CastNode visit(NotNAStep<?> step) { + public CastNode visit(NotNAStep<?> step, CastNode previous) { if (step.getReplacement() == null) { - MessageData msg = getDefaultErrorIfNull(step.getMessage()); - return NonNANodeGen.create(msg.getCallObj(), msg.getMessage(), msg.getMessageArgs(), step.getReplacement()); + MessageData msg = getDefaultIfNull(step.getMessage(), false); + return NonNANodeGen.create(msg, step.getReplacement()); } else { MessageData msg = step.getMessage(); if (msg == null) { - return NonNANodeGen.create(null, null, null, step.getReplacement()); + return NonNANodeGen.create(null, step.getReplacement()); } else { - return NonNANodeGen.create(msg.getCallObj(), msg.getMessage(), msg.getMessageArgs(), step.getReplacement()); + return NonNANodeGen.create(msg, step.getReplacement()); } } } @Override - public CastNode visit(CoercionStep<?, ?> step) { + public CastNode visit(CoercionStep<?, ?> step, CastNode previous) { boxPrimitives = true; RType type = step.getType(); switch (type) { case Integer: - return step.vectorCoercion ? CastIntegerNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, step.getMessageCallObj()) - : CastIntegerBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, step.getMessageCallObj()); + return step.vectorCoercion ? CastIntegerNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes) + : CastIntegerBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes); case Double: - return step.vectorCoercion ? CastDoubleNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, step.getMessageCallObj()) - : CastDoubleBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, step.getMessageCallObj()); + return step.vectorCoercion ? CastDoubleNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes) + : CastDoubleBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes); case Character: return step.vectorCoercion ? CastStringNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes) : CastStringBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes); case Logical: - return step.vectorCoercion ? CastLogicalNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, step.getMessageCallObj()) - : CastLogicalBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, step.getMessageCallObj()); + return step.vectorCoercion ? CastLogicalNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes) + : CastLogicalBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes); case Complex: - return CastComplexNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, step.getMessageCallObj()); + return CastComplexNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes); case Raw: return CastRawNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes); case Any: @@ -443,34 +248,27 @@ public final class PipelineToCastNode { } @Override - public CastNode visit(AttributableCoercionStep<?> step) { + public CastNode visit(AttributableCoercionStep<?> step, CastNode previous) { return CastToAttributableNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes); } @Override - public CastNode visit(MapStep<?, ?> step) { - return MapNode.create(mapperFactory.createMapper(step.getMapper())); + public CastNode visit(MapStep<?, ?> step, CastNode previous) { + return MapNode.create(ArgumentMapperFactoryImpl.INSTANCE.createMapper(step.getMapper())); } @Override - public CastNode visit(MapIfStep<?, ?> step) { - ArgumentFilter<?, ?> condition = filterFactory.createFilter(step.getFilter()); + public CastNode visit(MapIfStep<?, ?> step, CastNode previous) { + @SuppressWarnings("unchecked") + ArgumentFilter<Object, Object> condition = (ArgumentFilter<Object, Object>) ArgumentFilterFactoryImpl.INSTANCE.createFilter(step.getFilter()); CastNode trueCastNode = PipelineToCastNode.convert(step.getTrueBranch(), this); CastNode falseCastNode = PipelineToCastNode.convert(step.getFalseBranch(), this); return ConditionalMapNode.create(condition, trueCastNode, falseCastNode, ResultForArg.TRUE.equals(step.getFilter().resultForNull()), ResultForArg.TRUE.equals(step.getFilter().resultForMissing()), step.isReturns()); } - private MessageData getDefaultErrorIfNull(MessageData message) { - return MessageData.getFirstNonNull(message, defaultError, defaultMessage); - } - - private MessageData getDefaultWarningIfNull(MessageData message) { - return MessageData.getFirstNonNull(message, defaultWarning, defaultMessage); - } - private MessageData getDefaultIfNull(MessageData message, boolean isWarning) { - return isWarning ? getDefaultWarningIfNull(message) : getDefaultErrorIfNull(message); + return MessageData.getFirstNonNull(message, isWarning ? defaultWarning : defaultError); } } @@ -490,26 +288,54 @@ public final class PipelineToCastNode { @Override public ArgumentFilter<?, ?> createFilter(Filter<?, ?> filter) { - return filter.accept(this); + return filter.accept(this, null); } @Override - public ArgumentFilter<?, ?> visit(TypeFilter<?, ?> filter) { + public ArgumentFilter<?, ?> visit(TypeFilter<?, ?> filter, ArgumentFilter<?, ?> previous) { return filter.getInstanceOfLambda(); } @Override - public ArgumentFilter<?, ?> visit(RTypeFilter<?> filter) { + public ArgumentFilter<?, ?> visit(RTypeFilter<?> filter, ArgumentFilter<?, ?> previous) { if (filter.getType() == RType.Integer) { - return x -> x instanceof Integer || x instanceof RAbstractIntVector; + return new ArgumentFilter<Object, Object>() { + private final ConditionProfile profile = ConditionProfile.createBinaryProfile(); + + @Override + public boolean test(Object x) { + return profile.profile(x instanceof Integer) || x instanceof RAbstractIntVector; + } + }; } else if (filter.getType() == RType.Double) { - return x -> x instanceof Double || x instanceof RAbstractDoubleVector; + return new ArgumentFilter<Object, Object>() { + private final ConditionProfile profile = ConditionProfile.createBinaryProfile(); + + @Override + public boolean test(Object x) { + return profile.profile(x instanceof Double) || x instanceof RAbstractDoubleVector; + } + }; } else if (filter.getType() == RType.Logical) { - return x -> x instanceof Byte || x instanceof RAbstractLogicalVector; + return new ArgumentFilter<Object, Object>() { + private final ConditionProfile profile = ConditionProfile.createBinaryProfile(); + + @Override + public boolean test(Object x) { + return profile.profile(x instanceof Byte) || x instanceof RAbstractLogicalVector; + } + }; } else if (filter.getType() == RType.Complex) { return x -> x instanceof RAbstractComplexVector; } else if (filter.getType() == RType.Character) { - return x -> x instanceof String || x instanceof RAbstractStringVector; + return new ArgumentFilter<Object, Object>() { + private final ConditionProfile profile = ConditionProfile.createBinaryProfile(); + + @Override + public boolean test(Object x) { + return profile.profile(x instanceof String) || x instanceof RAbstractStringVector; + } + }; } else if (filter.getType() == RType.Raw) { return x -> x instanceof RAbstractRawVector; } else { @@ -518,87 +344,97 @@ public final class PipelineToCastNode { } @Override - public ArgumentFilter<?, ?> visit(CompareFilter<?> filter) { - return filter.getSubject().accept(this, filter.getOperation()); + public ArgumentFilter<?, ?> visit(CompareFilter<?> filter, ArgumentFilter<?, ?> previous) { + return filter.getSubject().accept(this, filter.getOperation(), previous); } @SuppressWarnings({"rawtypes", "unchecked"}) @Override - public ArgumentFilter<?, ?> visit(AndFilter<?, ?> filter) { - ArgumentFilter leftFilter = filter.getLeft().accept(this); - ArgumentFilter rightFilter = filter.getRight().accept(this); - return (ArgumentTypeFilter<Object, Object>) arg -> { - if (!leftFilter.test(arg)) { - return false; - } else { - return rightFilter.test(arg); + public ArgumentFilter<?, ?> visit(AndFilter<?, ?> filter, ArgumentFilter<?, ?> previous) { + ArgumentFilter leftFilter = filter.getLeft().accept(this, previous); + ArgumentFilter rightFilter = filter.getRight().accept(this, previous); + return new ArgumentTypeFilter<Object, Object>() { + private final ConditionProfile profile = ConditionProfile.createBinaryProfile(); + + @Override + public boolean test(Object arg) { + if (profile.profile(leftFilter.test(arg))) { + return rightFilter.test(arg); + } else { + return false; + } } }; } @SuppressWarnings({"rawtypes", "unchecked"}) @Override - public ArgumentFilter<?, ?> visit(OrFilter<?> filter) { - ArgumentFilter leftFilter = filter.getLeft().accept(this); - ArgumentFilter rightFilter = filter.getRight().accept(this); - return (ArgumentTypeFilter<Object, Object>) arg -> { - if (leftFilter.test(arg)) { - return true; - } else { - return rightFilter.test(arg); + public ArgumentFilter<?, ?> visit(OrFilter<?> filter, ArgumentFilter<?, ?> previous) { + ArgumentFilter leftFilter = filter.getLeft().accept(this, previous); + ArgumentFilter rightFilter = filter.getRight().accept(this, previous); + return new ArgumentTypeFilter<Object, Object>() { + private final ConditionProfile profile = ConditionProfile.createBinaryProfile(); + + @Override + public boolean test(Object arg) { + if (profile.profile(leftFilter.test(arg))) { + return true; + } else { + return rightFilter.test(arg); + } } }; } @SuppressWarnings({"rawtypes", "unchecked"}) @Override - public ArgumentFilter<?, ?> visit(NotFilter<?> filter) { - ArgumentFilter toNegate = filter.getFilter().accept(this); + public ArgumentFilter<?, ?> visit(NotFilter<?> filter, ArgumentFilter<?, ?> previous) { + ArgumentFilter toNegate = filter.getFilter().accept(this, previous); return (ArgumentFilter<Object, Object>) arg -> !toNegate.test(arg); } @Override - public ArgumentFilter<?, ?> visit(NullFilter filter) { + public ArgumentFilter<?, ?> visit(NullFilter filter, ArgumentFilter<?, ?> previous) { return (ArgumentFilter<Object, Object>) arg -> false; } @Override - public ArgumentFilter<?, ?> visit(MissingFilter filter) { + public ArgumentFilter<?, ?> visit(MissingFilter filter, ArgumentFilter<?, ?> previous) { return (ArgumentFilter<Object, Object>) arg -> false; } @Override - public ArgumentFilter<?, ?> visit(MatrixFilter<?> filter) { - return filter.acceptOperation(this); + public ArgumentFilter<?, ?> visit(MatrixFilter<?> filter, ArgumentFilter<?, ?> previous) { + return filter.acceptOperation(this, null); } @Override - public ArgumentFilter<?, ?> visit(DoubleFilter filter) { - return filter.acceptOperation(this); + public ArgumentFilter<?, ?> visit(DoubleFilter filter, ArgumentFilter<?, ?> previous) { + return filter.acceptOperation(this, null); } @Override - public ArgumentFilter<RAbstractVector, RAbstractVector> visitIsMatrix() { + public ArgumentFilter<RAbstractVector, RAbstractVector> visitIsMatrix(ArgumentFilter<RAbstractVector, RAbstractVector> previous) { return RAbstractVector::isMatrix; } @Override - public ArgumentFilter<RAbstractVector, RAbstractVector> visitIsSquareMatrix() { + public ArgumentFilter<RAbstractVector, RAbstractVector> visitIsSquareMatrix(ArgumentFilter<RAbstractVector, RAbstractVector> previous) { return x -> x.isMatrix() && x.getDimensions()[0] == x.getDimensions()[1]; } @Override - public ArgumentFilter<Double, Double> visitIsFinite() { + public ArgumentFilter<Double, Double> visitIsFinite(ArgumentFilter<Double, Double> previous) { return x -> !Double.isInfinite(x); } @Override - public ArgumentFilter<Double, Double> visitIsFractional() { + public ArgumentFilter<Double, Double> visitIsFractional(ArgumentFilter<Double, Double> previous) { return x -> !RRuntime.isNAorNaN(x) && !Double.isInfinite(x) && x != Math.floor(x); } @Override - public ArgumentFilter<?, ?> visit(ScalarValue scalarValue, byte operation) { + public ArgumentFilter<?, ?> visit(ScalarValue scalarValue, byte operation, ArgumentFilter<?, ?> previous) { switch (operation) { case CompareFilter.EQ: switch (scalarValue.type) { @@ -659,8 +495,8 @@ public final class PipelineToCastNode { default: throw RInternalError.unimplemented("TODO: more types here"); } - case CompareFilter.SAME: - return arg -> arg == scalarValue.value; + case CompareFilter.STRING_EQ: + return arg -> ((String) scalarValue.value).equals(arg); default: throw RInternalError.unimplemented("TODO: more operations here"); @@ -668,7 +504,7 @@ public final class PipelineToCastNode { } @Override - public ArgumentFilter<?, ?> visit(NATest naTest, byte operation) { + public ArgumentFilter<?, ?> visit(NATest naTest, byte operation, ArgumentFilter<?, ?> previous) { switch (operation) { case CompareFilter.EQ: switch (naTest.type) { @@ -691,7 +527,7 @@ public final class PipelineToCastNode { } @Override - public ArgumentFilter<String, String> visit(StringLength stringLength, byte operation) { + public ArgumentFilter<String, String> visit(StringLength stringLength, byte operation, ArgumentFilter<?, ?> previous) { switch (operation) { case CompareFilter.EQ: return arg -> arg.length() == stringLength.length; @@ -714,7 +550,7 @@ public final class PipelineToCastNode { } @Override - public ArgumentFilter<RAbstractVector, RAbstractVector> visit(VectorSize vectorSize, byte operation) { + public ArgumentFilter<RAbstractVector, RAbstractVector> visit(VectorSize vectorSize, byte operation, ArgumentFilter<?, ?> previous) { switch (operation) { case CompareFilter.EQ: return arg -> arg.getLength() == vectorSize.size; @@ -737,7 +573,7 @@ public final class PipelineToCastNode { } @Override - public ArgumentFilter<RAbstractVector, RAbstractVector> visit(ElementAt elementAt, byte operation) { + public ArgumentFilter<RAbstractVector, RAbstractVector> visit(ElementAt elementAt, byte operation, ArgumentFilter<?, ?> previous) { switch (operation) { case CompareFilter.EQ: switch (elementAt.type) { @@ -759,7 +595,7 @@ public final class PipelineToCastNode { } @Override - public ArgumentFilter<RAbstractVector, RAbstractVector> visit(Dim dim, byte operation) { + public ArgumentFilter<RAbstractVector, RAbstractVector> visit(Dim dim, byte operation, ArgumentFilter<?, ?> previous) { switch (operation) { case CompareFilter.EQ: return v -> v.isMatrix() && v.getDimensions().length > dim.dimIndex && v.getDimensions()[dim.dimIndex] == dim.dimSize; @@ -785,22 +621,22 @@ public final class PipelineToCastNode { @Override public ArgumentMapper<Object, Object> createMapper(Mapper<?, ?> mapper) { - return mapper.accept(this); + return mapper.accept(this, null); } @Override - public ValuePredicateArgumentMapper<Object, Object> visit(MapToValue<?, ?> mapper) { + public ValuePredicateArgumentMapper<Object, Object> visit(MapToValue<?, ?> mapper, ValuePredicateArgumentMapper<Object, Object> previous) { final Object value = mapper.getValue(); return ValuePredicateArgumentMapper.fromLambda(x -> value); } @Override - public ValuePredicateArgumentMapper<Object, Object> visit(MapByteToBoolean mapper) { - return ValuePredicateArgumentMapper.fromLambda(x -> RRuntime.fromLogical((Byte) x)); + public ValuePredicateArgumentMapper<Object, Object> visit(MapByteToBoolean mapper, ValuePredicateArgumentMapper<Object, Object> previous) { + return ValuePredicateArgumentMapper.fromLambda(x -> RRuntime.fromLogical((Byte) x, mapper.naReplacement)); } @Override - public ValuePredicateArgumentMapper<Object, Object> visit(MapDoubleToInt mapper) { + public ValuePredicateArgumentMapper<Object, Object> visit(MapDoubleToInt mapper, ValuePredicateArgumentMapper<Object, Object> previous) { final NACheck naCheck = NACheck.create(); return ValuePredicateArgumentMapper.fromLambda(x -> { double d = (Double) x; @@ -810,7 +646,7 @@ public final class PipelineToCastNode { } @Override - public ValuePredicateArgumentMapper<Object, Object> visit(MapToCharAt mapper) { + public ValuePredicateArgumentMapper<Object, Object> visit(MapToCharAt mapper, ValuePredicateArgumentMapper<Object, Object> previous) { final int defaultValue = mapper.getDefaultValue(); final int index = mapper.getIndex(); return ValuePredicateArgumentMapper.fromLambda(x -> { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ValueForwardingNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ValueForwardingNode.java index f3baa1bb85619beb3f27fda1a4854efa424047f8..362ec3b4ee7c74596b199531ea06f43de4184d55 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ValueForwardingNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ValueForwardingNode.java @@ -65,7 +65,7 @@ public abstract class ValueForwardingNode extends CastNode { @Specialization(guards = "forwardingResult.isLogicalMappedToBoolean()") protected boolean mapLogicalToBoolean(byte x) { - return RRuntime.fromLogical(x); + return RRuntime.fromLogical(x, forwardingResult.getMapByteToBooleanNAMapping()); } @Specialization(guards = "forwardingResult.isDoubleForwarded()") @@ -89,6 +89,6 @@ public abstract class ValueForwardingNode extends CastNode { @Specialization protected Object executeOriginalPipeline(Object x, @Cached("createPipeline()") CastNode pipelineHeadNode) { - return pipelineHeadNode.execute(x); + return pipelineHeadNode.doCast(x); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardedValuesAnalyser.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardedValuesAnalyser.java index ce9b228102be545d716a1ea095ac28a2b431ba7c..4eb716c6cc7c54b9b890ec5fed978a2969f7d3ac 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardedValuesAnalyser.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardedValuesAnalyser.java @@ -52,8 +52,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.AttributableCoercionStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.BoxPrimitiveStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep; -import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultErrorStep; -import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultWarningStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep; @@ -70,7 +68,7 @@ public final class ForwardedValuesAnalyser implements PipelineStepVisitor<Forwar private ForwardingAnalysisResult altResult = null; public ForwardingAnalysisResult analyse(PipelineStep<?, ?> firstStep) { - firstStep.acceptPipeline(this); + firstStep.acceptPipeline(this, null); ForwardingAnalysisResult mainRes = result; if (altResult != null) { mainRes = mainRes.or(altResult); @@ -87,7 +85,7 @@ public final class ForwardedValuesAnalyser implements PipelineStepVisitor<Forwar } @Override - public ForwardingAnalysisResult visit(FindFirstStep<?, ?> step) { + public ForwardingAnalysisResult visit(FindFirstStep<?, ?> step, ForwardingAnalysisResult previous) { ForwardingAnalysisResult localRes = new ForwardingAnalysisResult().blockAll().setForwardedType(step.getElementClass(), FORWARDED); if (step.getDefaultValue() == RNull.instance) { // see CoercedPhaseBuilder.findFirstOrNull() @@ -98,7 +96,7 @@ public final class ForwardedValuesAnalyser implements PipelineStepVisitor<Forwar } @Override - public ForwardingAnalysisResult visit(CoercionStep<?, ?> step) { + public ForwardingAnalysisResult visit(CoercionStep<?, ?> step, ForwardingAnalysisResult previous) { ForwardingAnalysisResult localRes = new ForwardingAnalysisResult().blockAll().setForwardedType(step.getType(), FORWARDED); if (step.preserveNonVector) { // i.e. preserve NULL and MISSING @@ -109,35 +107,35 @@ public final class ForwardedValuesAnalyser implements PipelineStepVisitor<Forwar } @Override - public ForwardingAnalysisResult visit(MapStep<?, ?> step) { + public ForwardingAnalysisResult visit(MapStep<?, ?> step, ForwardingAnalysisResult previous) { ForwardingAnalysisResult localRes = step.getMapper().accept(new Mapper.MapperVisitor<ForwardingAnalysisResult>() { @Override - public ForwardingAnalysisResult visit(MapToValue<?, ?> mapper) { + public ForwardingAnalysisResult visit(MapToValue<?, ?> mapper, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { return ForwardingAnalysisResult.INVALID; } @Override - public ForwardingAnalysisResult visit(MapByteToBoolean mapper) { + public ForwardingAnalysisResult visit(MapByteToBoolean mapper, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { return new ForwardingAnalysisResult().blockAll().setForwardedType(RType.Logical, new Forwarded(mapper)); } @Override - public ForwardingAnalysisResult visit(MapDoubleToInt mapper) { + public ForwardingAnalysisResult visit(MapDoubleToInt mapper, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { return ForwardingAnalysisResult.INVALID; } @Override - public ForwardingAnalysisResult visit(MapToCharAt mapper) { + public ForwardingAnalysisResult visit(MapToCharAt mapper, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { return ForwardingAnalysisResult.INVALID; } - }); + }, previous); result = result.and(localRes); return result; } @Override - public ForwardingAnalysisResult visit(MapIfStep<?, ?> mapIfStep) { + public ForwardingAnalysisResult visit(MapIfStep<?, ?> mapIfStep, ForwardingAnalysisResult previous) { // analyze the true branch ForwardingAnalysisResult trueBranchFwdRes; PipelineStep<?, ?> trueBranchFirstStep = new FilterStep<>(mapIfStep.getFilter(), null, false); @@ -167,11 +165,11 @@ public final class ForwardedValuesAnalyser implements PipelineStepVisitor<Forwar } @Override - public ForwardingAnalysisResult visit(FilterStep<?, ?> step) { + public ForwardingAnalysisResult visit(FilterStep<?, ?> step, ForwardingAnalysisResult previous) { class ForwardedValuesFilterVisitor implements Filter.FilterVisitor<ForwardingAnalysisResult> { @Override - public ForwardingAnalysisResult visit(TypeFilter<?, ?> filter) { + public ForwardingAnalysisResult visit(TypeFilter<?, ?> filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { ForwardingAnalysisResult res = new ForwardingAnalysisResult().blockAll(); if (filter.getExtraCondition() == null) { res = res.setForwardedType(filter.getType1(), FORWARDED); @@ -182,31 +180,31 @@ public final class ForwardedValuesAnalyser implements PipelineStepVisitor<Forwar } @Override - public ForwardingAnalysisResult visit(RTypeFilter<?> filter) { + public ForwardingAnalysisResult visit(RTypeFilter<?> filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { return new ForwardingAnalysisResult().blockAll().setForwardedType(filter.getType(), FORWARDED); } @Override - public ForwardingAnalysisResult visit(CompareFilter<?> filter) { + public ForwardingAnalysisResult visit(CompareFilter<?> filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { return filter.getSubject().accept(new Filter.CompareFilter.SubjectVisitor<ForwardingAnalysisResult>() { @Override - public ForwardingAnalysisResult visit(ScalarValue scalarValue, byte operation) { + public ForwardingAnalysisResult visit(ScalarValue scalarValue, byte operation, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { return new ForwardingAnalysisResult().blockAll().setForwardedType(scalarValue.type, UNKNOWN); } @Override - public ForwardingAnalysisResult visit(NATest naTest, byte operation) { + public ForwardingAnalysisResult visit(NATest naTest, byte operation, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { return new ForwardingAnalysisResult().blockAll().setForwardedType(naTest.type, UNKNOWN); } @Override - public ForwardingAnalysisResult visit(StringLength stringLength, byte operation) { + public ForwardingAnalysisResult visit(StringLength stringLength, byte operation, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { return new ForwardingAnalysisResult().blockAll().setForwardedType(RType.Character, UNKNOWN); } @Override - public ForwardingAnalysisResult visit(VectorSize vectorSize, byte operation) { + public ForwardingAnalysisResult visit(VectorSize vectorSize, byte operation, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { if (vectorSize.size == 0 && operation == CompareFilter.EQ) { return new ForwardingAnalysisResult().blockAll().setNull(FORWARDED); } else if (vectorSize.size == 1 && (operation == CompareFilter.EQ || operation == CompareFilter.GT || operation == CompareFilter.GE)) { @@ -221,7 +219,7 @@ public final class ForwardedValuesAnalyser implements PipelineStepVisitor<Forwar } @Override - public ForwardingAnalysisResult visit(ElementAt elementAt, byte operation) { + public ForwardingAnalysisResult visit(ElementAt elementAt, byte operation, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { if (elementAt.index == 0) { return new ForwardingAnalysisResult().blockAll().setForwardedType(elementAt.type, UNKNOWN); } else { @@ -230,86 +228,76 @@ public final class ForwardedValuesAnalyser implements PipelineStepVisitor<Forwar } @Override - public ForwardingAnalysisResult visit(Dim dim, byte operation) { + public ForwardingAnalysisResult visit(Dim dim, byte operation, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { return new ForwardingAnalysisResult().blockAll(); } - }, filter.getOperation()); + }, filter.getOperation(), previous); } @Override - public ForwardingAnalysisResult visit(AndFilter<?, ?> filter) { + public ForwardingAnalysisResult visit(AndFilter<?, ?> filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { ForwardedValuesFilterVisitor leftVis = new ForwardedValuesFilterVisitor(); ForwardedValuesFilterVisitor rightVis = new ForwardedValuesFilterVisitor(); - ForwardingAnalysisResult leftResult = filter.getLeft().accept(leftVis); - ForwardingAnalysisResult rightResult = filter.getRight().accept(rightVis); + ForwardingAnalysisResult leftResult = filter.getLeft().accept(leftVis, previous); + ForwardingAnalysisResult rightResult = filter.getRight().accept(rightVis, previous); return leftResult.and(rightResult); } @Override - public ForwardingAnalysisResult visit(OrFilter<?> filter) { + public ForwardingAnalysisResult visit(OrFilter<?> filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { ForwardedValuesFilterVisitor leftVis = new ForwardedValuesFilterVisitor(); ForwardedValuesFilterVisitor rightVis = new ForwardedValuesFilterVisitor(); - ForwardingAnalysisResult leftResult = filter.getLeft().accept(leftVis); - ForwardingAnalysisResult rightResult = filter.getRight().accept(rightVis); + ForwardingAnalysisResult leftResult = filter.getLeft().accept(leftVis, previous); + ForwardingAnalysisResult rightResult = filter.getRight().accept(rightVis, previous); return leftResult.or(rightResult); } @Override - public ForwardingAnalysisResult visit(NotFilter<?> filter) { + public ForwardingAnalysisResult visit(NotFilter<?> filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { ForwardedValuesFilterVisitor vis = new ForwardedValuesFilterVisitor(); - return filter.getFilter().accept(vis).not(); + return filter.getFilter().accept(vis, previous).not(); } @Override - public ForwardingAnalysisResult visit(MatrixFilter<?> filter) { - return new ForwardingAnalysisResult().forwardAll(); + public ForwardingAnalysisResult visit(MatrixFilter<?> filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { + return new ForwardingAnalysisResult().blockAll(); } @Override - public ForwardingAnalysisResult visit(DoubleFilter filter) { + public ForwardingAnalysisResult visit(DoubleFilter filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { return new ForwardingAnalysisResult().blockAll().setForwardedType(RType.Double, UNKNOWN); } @Override - public ForwardingAnalysisResult visit(NullFilter filter) { + public ForwardingAnalysisResult visit(NullFilter filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { return new ForwardingAnalysisResult().blockAll().setNull(FORWARDED); } @Override - public ForwardingAnalysisResult visit(MissingFilter filter) { + public ForwardingAnalysisResult visit(MissingFilter filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) { return new ForwardingAnalysisResult().blockAll().setMissing(FORWARDED); } } - ForwardingAnalysisResult localRes = step.getFilter().accept(new ForwardedValuesFilterVisitor()); + ForwardingAnalysisResult localRes = step.getFilter().accept(new ForwardedValuesFilterVisitor(), previous); result = result.and(localRes); return result; } @Override - public ForwardingAnalysisResult visit(NotNAStep<?> step) { + public ForwardingAnalysisResult visit(NotNAStep<?> step, ForwardingAnalysisResult previous) { result = result.and(new ForwardingAnalysisResult().unknownAll().setNull(FORWARDED).setMissing(FORWARDED)); return result; } @Override - public ForwardingAnalysisResult visit(DefaultErrorStep<?> step) { - return result; - } - - @Override - public ForwardingAnalysisResult visit(DefaultWarningStep<?> step) { - return result; - } - - @Override - public ForwardingAnalysisResult visit(BoxPrimitiveStep<?> step) { + public ForwardingAnalysisResult visit(BoxPrimitiveStep<?> step, ForwardingAnalysisResult previous) { // TODO result = ForwardingAnalysisResult.INVALID; return result; } @Override - public ForwardingAnalysisResult visit(AttributableCoercionStep<?> step) { + public ForwardingAnalysisResult visit(AttributableCoercionStep<?> step, ForwardingAnalysisResult previous) { // TODO result = ForwardingAnalysisResult.INVALID; return result; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingAnalysisResult.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingAnalysisResult.java index 353156736aef1612b6b8550f02327fc8dd858969..c5323e2aea1425addbcae0210b9a50f1a753cd89 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingAnalysisResult.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingAnalysisResult.java @@ -41,7 +41,7 @@ public final class ForwardingAnalysisResult { public final ForwardingStatus missingForwarded; public final boolean invalid; - static final ForwardingAnalysisResult INVALID = new ForwardingAnalysisResult(UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, true); + public static final ForwardingAnalysisResult INVALID = new ForwardingAnalysisResult(UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, true); ForwardingAnalysisResult() { this(UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, false); @@ -82,7 +82,12 @@ public final class ForwardingAnalysisResult { } public boolean isLogicalMappedToBoolean() { - return !invalid && logicalForwarded.mapper == MapByteToBoolean.INSTANCE; + return !invalid && logicalForwarded.mapper instanceof MapByteToBoolean; + } + + public boolean getMapByteToBooleanNAMapping() { + assert logicalForwarded.mapper instanceof MapByteToBoolean : "check isLogicalMappedToBoolean() before calling this method"; + return ((MapByteToBoolean) logicalForwarded.mapper).naReplacement; } public boolean isDoubleForwarded() { @@ -98,7 +103,7 @@ public final class ForwardingAnalysisResult { } public boolean isAnythingForwarded() { - return isNullForwarded() || isMissingForwarded() || isIntegerForwarded() || isLogicalForwarded() || isDoubleForwarded() || isComplexForwarded() || isStringForwarded(); + return !invalid && (isNullForwarded() || isMissingForwarded() || isIntegerForwarded() || isLogicalForwarded() || isDoubleForwarded() || isComplexForwarded() || isStringForwarded()); } ForwardingAnalysisResult setForwardedType(Class<?> tp, ForwardingStatus status) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingStatus.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingStatus.java index a59b7c04358ce5fb1082ad0ce8fc5e88288ccd3d..c8fb811228400ddc74a78045c5d8bb38f83da2cd 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingStatus.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingStatus.java @@ -39,7 +39,7 @@ public abstract class ForwardingStatus { }; public static final ForwardingStatus FORWARDED = new Forwarded(null); - final Mapper<?, ?> mapper; + public final Mapper<?, ?> mapper; private final byte flag; protected ForwardingStatus(byte flag, Mapper<?, ?> mapper) { @@ -97,7 +97,7 @@ public abstract class ForwardingStatus { } ForwardingStatus or(ForwardingStatus other) { - return fromFlag(or(this.flag, other.flag)); + return fromFlag(or(this.flag, other.flag), this.mapper != null ? this.mapper : other.mapper); } ForwardingStatus not() { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ArgCastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ArgCastBuilder.java index 4d2390aeb594fc9a4efe021acc8f24dbdf3f93fb..13fa1d39b4675a9ccd159b08843bc32162ac1aed 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ArgCastBuilder.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ArgCastBuilder.java @@ -27,7 +27,6 @@ import java.util.function.Function; import com.oracle.truffle.r.nodes.builtin.casts.Filter; import com.oracle.truffle.r.nodes.unary.CastNode; import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; /** * Defines fluent API methods for building cast pipeline steps that are available in every phase of @@ -46,33 +45,13 @@ public class ArgCastBuilder<T, THIS> { return builder; } - public THIS defaultError(RBaseNode callObj, RError.Message message, Object... args) { - pipelineBuilder().appendDefaultErrorStep(callObj, message, args); - return (THIS) this; - } - - public THIS defaultError(RError.Message message, Object... args) { - defaultError(null, message, args); - return (THIS) this; - } - - public THIS defaultWarning(RBaseNode callObj, RError.Message message, Object... args) { - pipelineBuilder().appendDefaultWarningStep(callObj, message, args); - return (THIS) this; - } - public THIS shouldBe(Filter<? super T, ?> argFilter, RError.Message message, Object... messageArgs) { pipelineBuilder().appendShouldBeStep(argFilter, message, messageArgs); return (THIS) this; } - public THIS shouldBe(Filter<? super T, ?> argFilter, RBaseNode callObj, RError.Message message, Object... messageArgs) { - pipelineBuilder().appendShouldBeStep(argFilter, callObj, message, messageArgs); - return (THIS) this; - } - public THIS shouldBe(Filter<? super T, ?> argFilter) { - pipelineBuilder().appendShouldBeStep(argFilter, null, null, null); + pipelineBuilder().appendShouldBeStep(argFilter, null, null); return (THIS) this; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CastNodeBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CastNodeBuilder.java index aae3576a5a8c733cb5316a53df9dde46a134374f..a6930c3a41e83663675e77156f3188534ffa7a4f 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CastNodeBuilder.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CastNodeBuilder.java @@ -27,11 +27,7 @@ package com.oracle.truffle.r.nodes.builtin.casts.fluent; * be then used to cast anything, not only arguments. */ public final class CastNodeBuilder { - public static PreinitialPhaseBuilder newCastBuilder(String argName) { - return new PipelineBuilder(argName).fluent(); - } - public static PreinitialPhaseBuilder newCastBuilder() { - return newCastBuilder(""); + return new PipelineBuilder("").fluent(); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CoercedPhaseBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CoercedPhaseBuilder.java index 5ced98be0f64a429c7b6debd151e8433d540bf00..05384ae850f7ace3eaeb53244c934413f39dd09f 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CoercedPhaseBuilder.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CoercedPhaseBuilder.java @@ -22,11 +22,11 @@ */ package com.oracle.truffle.r.nodes.builtin.casts.fluent; +import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; import com.oracle.truffle.r.nodes.builtin.casts.Filter; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; /** * Defines fluent API methods for building cast pipeline steps for argument that has been cast to a @@ -49,12 +49,7 @@ public final class CoercedPhaseBuilder<T extends RAbstractVector, S> extends Arg * reports the warning message. */ public HeadPhaseBuilder<S> findFirst(S defaultValue, RError.Message message, Object... messageArgs) { - pipelineBuilder().appendFindFirst(defaultValue, elementClass, null, message, messageArgs); - return new HeadPhaseBuilder<>(pipelineBuilder()); - } - - public HeadPhaseBuilder<S> findFirst(S defaultValue, RBaseNode callObj, RError.Message message, Object... messageArgs) { - pipelineBuilder().appendFindFirst(defaultValue, elementClass, callObj, message, messageArgs); + pipelineBuilder().appendFindFirst(defaultValue, elementClass, message, messageArgs); return new HeadPhaseBuilder<>(pipelineBuilder()); } @@ -62,12 +57,7 @@ public final class CoercedPhaseBuilder<T extends RAbstractVector, S> extends Arg * The inserted cast node raises an error if the input vector is empty. */ public HeadPhaseBuilder<S> findFirst(RError.Message message, Object... messageArgs) { - pipelineBuilder().appendFindFirst(null, elementClass, null, message, messageArgs); - return new HeadPhaseBuilder<>(pipelineBuilder()); - } - - public HeadPhaseBuilder<S> findFirst(RBaseNode callObj, RError.Message message, Object... messageArgs) { - pipelineBuilder().appendFindFirst(null, elementClass, callObj, message, messageArgs); + pipelineBuilder().appendFindFirst(null, elementClass, message, messageArgs); return new HeadPhaseBuilder<>(pipelineBuilder()); } @@ -76,7 +66,7 @@ public final class CoercedPhaseBuilder<T extends RAbstractVector, S> extends Arg * error if the input vector is empty. */ public HeadPhaseBuilder<S> findFirst() { - pipelineBuilder().appendFindFirst(null, elementClass, null, null, null); + pipelineBuilder().appendFindFirst(null, elementClass, null, null); return new HeadPhaseBuilder<>(pipelineBuilder()); } @@ -86,26 +76,26 @@ public final class CoercedPhaseBuilder<T extends RAbstractVector, S> extends Arg */ public HeadPhaseBuilder<S> findFirst(S defaultValue) { assert defaultValue != null : "defaultValue cannot be null"; - pipelineBuilder().appendFindFirst(defaultValue, elementClass, null, null, null); + pipelineBuilder().appendFindFirst(defaultValue, elementClass, null, null); return new HeadPhaseBuilder<>(pipelineBuilder()); } public HeadPhaseBuilder<S> findFirstOrNull() { - pipelineBuilder().appendFindFirst(RNull.instance, elementClass, null, null, null); + pipelineBuilder().appendFindFirst(RNull.instance, elementClass, null, null); return new HeadPhaseBuilder<>(pipelineBuilder()); } - public CoercedPhaseBuilder<T, S> mustBe(Filter<? super T, ? extends T> argFilter, RBaseNode callObj, RError.Message message, Object... messageArgs) { - pipelineBuilder().appendMustBeStep(argFilter, callObj, message, messageArgs); - return this; - } - public CoercedPhaseBuilder<T, S> mustBe(Filter<? super T, ? extends T> argFilter, RError.Message message, Object... messageArgs) { - pipelineBuilder().appendMustBeStep(argFilter, null, message, messageArgs); + pipelineBuilder().appendMustBeStep(argFilter, message, messageArgs); return this; } public CoercedPhaseBuilder<T, S> mustBe(Filter<? super T, ? extends T> argFilter) { return mustBe(argFilter, null, null, (Object[]) null); } + + @SuppressWarnings("unchecked") + public <R extends T> CoercedPhaseBuilder<R, S> mustBe(Class<R> cls) { + return (CoercedPhaseBuilder<R, S>) mustBe(Predef.instanceOf(cls)); + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/FindFirstNodeBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/FindFirstNodeBuilder.java index 28c5619018f95fbb8cd9596bc4576723626a9c57..c5b0f8e93c03acfca8a9fb8fa615935e78e692ab 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/FindFirstNodeBuilder.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/FindFirstNodeBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.builtin.casts.fluent; import com.oracle.truffle.r.nodes.builtin.casts.MessageData; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep; -import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; @@ -33,25 +32,20 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; /** * Allows to convert find first into a valid step when used in {@code chain}, for example * {@code chain(findFirst().stringElement())}. */ public final class FindFirstNodeBuilder { - private final RBaseNode callObj; - private final Message message; - private final Object[] messageArgs; + private final MessageData message; - public FindFirstNodeBuilder(RBaseNode callObj, Message message, Object[] messageArgs) { - this.callObj = callObj; + public FindFirstNodeBuilder(MessageData message) { this.message = message; - this.messageArgs = messageArgs; } private <V, E> PipelineStep<V, E> create(Class<?> elementClass, Object defaultValue) { - return new FindFirstStep<>(defaultValue, elementClass, new MessageData(callObj, message, messageArgs)); + return new FindFirstStep<>(defaultValue, elementClass, message); } public PipelineStep<RAbstractLogicalVector, Byte> logicalElement() { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/HeadPhaseBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/HeadPhaseBuilder.java index 6d0d72eb972efbd59ccb569ab971268fa2a39f90..3317318400047e90939dc093acabda11f28aa54c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/HeadPhaseBuilder.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/HeadPhaseBuilder.java @@ -27,13 +27,13 @@ import com.oracle.truffle.r.nodes.builtin.casts.Filter; import com.oracle.truffle.r.nodes.builtin.casts.Mapper; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep; import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; /** * Defines fluent API methods for building cast pipeline steps for a value that has been taken as a * head of a vector. This is the last phase in the pipeline building fluent API and comes after * {@link CoercedPhaseBuilder} phase. */ +@SuppressWarnings("unchecked") public final class HeadPhaseBuilder<T> extends ArgCastBuilder<T, HeadPhaseBuilder<T>> { public HeadPhaseBuilder(PipelineBuilder builder) { @@ -43,62 +43,57 @@ public final class HeadPhaseBuilder<T> extends ArgCastBuilder<T, HeadPhaseBuilde public <S> HeadPhaseBuilder<S> map(Mapper<T, S> mapFn) { // state().castBuilder().insert(state().index(), () -> MapNode.create(mapFn)); pipelineBuilder().appendMap(mapFn); - return new HeadPhaseBuilder<>(pipelineBuilder()); + return (HeadPhaseBuilder<S>) this; } public HeadPhaseBuilder<Object> returnIf(Filter<? super T, ?> argFilter) { pipelineBuilder().appendMapIf(argFilter, (PipelineStep<?, ?>) null, (PipelineStep<?, ?>) null, true); - return new HeadPhaseBuilder<>(pipelineBuilder()); + return (HeadPhaseBuilder<Object>) this; } public <S extends T, R> HeadPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper) { pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, false); - return new HeadPhaseBuilder<>(pipelineBuilder()); + return (HeadPhaseBuilder<Object>) this; } - public <S extends T, R> HeadPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper) { + public <S extends T, R> HeadPhaseBuilder<T> returnIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper) { pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, true); - return new HeadPhaseBuilder<>(pipelineBuilder()); + return this; } public <S extends T, R> HeadPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper, Mapper<T, ?> falseBranchMapper) { pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, falseBranchMapper, false); - return new HeadPhaseBuilder<>(pipelineBuilder()); + return (HeadPhaseBuilder<Object>) this; } public <S extends T, R> HeadPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper, Mapper<T, ?> falseBranchMapper) { pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, falseBranchMapper, true); - return new HeadPhaseBuilder<>(pipelineBuilder()); + return (HeadPhaseBuilder<Object>) this; } public <S extends T, R> HeadPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, PipelineStep<S, ?> trueBranch) { pipelineBuilder().appendMapIf(argFilter, trueBranch, false); - return new HeadPhaseBuilder<>(pipelineBuilder()); + return (HeadPhaseBuilder<Object>) this; } public <S extends T, R> HeadPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, PipelineStep<S, ?> trueBranch) { pipelineBuilder().appendMapIf(argFilter, trueBranch, true); - return new HeadPhaseBuilder<>(pipelineBuilder()); + return (HeadPhaseBuilder<Object>) this; } public <S extends T, R> HeadPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, PipelineStep<S, R> trueBranch, PipelineStep<T, ?> falseBranch) { pipelineBuilder().appendMapIf(argFilter, trueBranch, falseBranch, false); - return new HeadPhaseBuilder<>(pipelineBuilder()); + return (HeadPhaseBuilder<Object>) this; } public <S extends T, R> HeadPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, PipelineStep<S, R> trueBranch, PipelineStep<T, ?> falseBranch) { pipelineBuilder().appendMapIf(argFilter, trueBranch, falseBranch, true); - return new HeadPhaseBuilder<>(pipelineBuilder()); - } - - public <S extends T> HeadPhaseBuilder<S> mustBe(Filter<? super T, S> argFilter, RBaseNode callObj, RError.Message message, Object... messageArgs) { - pipelineBuilder().appendMustBeStep(argFilter, callObj, message, messageArgs); - return new HeadPhaseBuilder<>(pipelineBuilder()); + return (HeadPhaseBuilder<Object>) this; } public <S extends T> HeadPhaseBuilder<S> mustBe(Filter<? super T, S> argFilter, RError.Message message, Object... messageArgs) { - pipelineBuilder().appendMustBeStep(argFilter, null, message, messageArgs); - return new HeadPhaseBuilder<>(pipelineBuilder()); + pipelineBuilder().appendMustBeStep(argFilter, message, messageArgs); + return (HeadPhaseBuilder<S>) this; } public <S extends T> HeadPhaseBuilder<S> mustBe(Filter<? super T, S> argFilter) { @@ -107,56 +102,41 @@ public final class HeadPhaseBuilder<T> extends ArgCastBuilder<T, HeadPhaseBuilde public <S extends T> HeadPhaseBuilder<S> mustBe(Class<S> cls, RError.Message message, Object... messageArgs) { mustBe(Predef.instanceOf(cls), message, messageArgs); - return new HeadPhaseBuilder<>(pipelineBuilder()); + return (HeadPhaseBuilder<S>) this; } public <S extends T> HeadPhaseBuilder<S> mustBe(Class<S> cls) { mustBe(Predef.instanceOf(cls)); - return new HeadPhaseBuilder<>(pipelineBuilder()); - } - - public <S> HeadPhaseBuilder<S> shouldBe(Class<S> cls, RBaseNode callObj, RError.Message message, Object... messageArgs) { - shouldBe(Predef.instanceOf(cls), callObj, message, messageArgs); - return new HeadPhaseBuilder<>(pipelineBuilder()); + return (HeadPhaseBuilder<S>) this; } public <S> HeadPhaseBuilder<S> shouldBe(Class<S> cls, RError.Message message, Object... messageArgs) { shouldBe(Predef.instanceOf(cls), message, messageArgs); - return new HeadPhaseBuilder<>(pipelineBuilder()); + return (HeadPhaseBuilder<S>) this; } public <S> HeadPhaseBuilder<S> shouldBe(Class<S> cls) { shouldBe(Predef.instanceOf(cls)); - return new HeadPhaseBuilder<>(pipelineBuilder()); - } - - public HeadPhaseBuilder<T> notNA(RBaseNode callObj, RError.Message message, Object... messageArgs) { - pipelineBuilder().appendNotNA(null, callObj, message, messageArgs); - return this; - } - - public HeadPhaseBuilder<T> notNA(RError.Message message, Object... messageArgs) { - pipelineBuilder().appendNotNA(null, null, message, messageArgs); - return this; + return (HeadPhaseBuilder<S>) this; } - public HeadPhaseBuilder<T> notNA(T naReplacement, RBaseNode callObj, RError.Message message, Object... messageArgs) { - pipelineBuilder().appendNotNA(naReplacement, callObj, message, messageArgs); + public HeadPhaseBuilder<T> mustNotBeNA(RError.Message message, Object... messageArgs) { + pipelineBuilder().appendNotNA(null, message, messageArgs); return this; } - public HeadPhaseBuilder<T> notNA(T naReplacement, RError.Message message, Object... messageArgs) { - pipelineBuilder().appendNotNA(naReplacement, null, message, messageArgs); + public HeadPhaseBuilder<T> shouldNotBeNA(T naReplacement, RError.Message message, Object... messageArgs) { + pipelineBuilder().appendNotNA(naReplacement, message, messageArgs); return this; } - public HeadPhaseBuilder<T> notNA() { - pipelineBuilder().appendNotNA(null, null, null, null); + public HeadPhaseBuilder<T> mustNotBeNA() { + pipelineBuilder().appendNotNA(null, null, null); return this; } - public HeadPhaseBuilder<T> notNA(T naReplacement) { - pipelineBuilder().appendNotNA(naReplacement, null, null, null); + public HeadPhaseBuilder<T> replaceNA(T naReplacement) { + pipelineBuilder().appendNotNA(naReplacement, null, null); return this; } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java index 58fe88bbdc18017e032a9af5d292c7a4e705dc6a..c66079bf6e6e723802b7c99c7355f7918945afdb 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java @@ -38,134 +38,110 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; /** * Defines fluent API methods for building cast pipeline steps for generic argument, which was not * cast to any specific type yet. Any method that represents casting of the argument to a specific * type returns instance of {@link CoercedPhaseBuilder} with its generic parameters set accordingly. */ +@SuppressWarnings("unchecked") public class InitialPhaseBuilder<T> extends ArgCastBuilder<T, InitialPhaseBuilder<T>> { public InitialPhaseBuilder(PipelineBuilder builder) { super(builder); } - public <S extends T> InitialPhaseBuilder<S> mustBe(Filter<? super T, S> argFilter, RBaseNode callObj, RError.Message message, Object... messageArgs) { - pipelineBuilder().appendMustBeStep(argFilter, callObj, message, messageArgs); - return new InitialPhaseBuilder<>(pipelineBuilder()); - } - public <S extends T> InitialPhaseBuilder<S> mustBe(Filter<? super T, S> argFilter, RError.Message message, Object... messageArgs) { - return mustBe(argFilter, null, message, messageArgs); + pipelineBuilder().appendMustBeStep(argFilter, message, messageArgs); + return (InitialPhaseBuilder<S>) this; } public <S extends T> InitialPhaseBuilder<S> mustBe(Filter<? super T, S> argFilter) { - return mustBe(argFilter, null, null, (Object[]) null); - } - - public <S extends T> InitialPhaseBuilder<S> mustBe(Class<S> cls, RBaseNode callObj, RError.Message message, Object... messageArgs) { - mustBe(Predef.instanceOf(cls), callObj, message, messageArgs); - return new InitialPhaseBuilder<>(pipelineBuilder()); + return mustBe(argFilter, null, (Object[]) null); } public <S extends T> InitialPhaseBuilder<S> mustBe(Class<S> cls, RError.Message message, Object... messageArgs) { mustBe(Predef.instanceOf(cls), message, messageArgs); - return new InitialPhaseBuilder<>(pipelineBuilder()); + return (InitialPhaseBuilder<S>) this; } public <S extends T> InitialPhaseBuilder<S> mustBe(Class<S> cls) { mustBe(Predef.instanceOf(cls)); - return new InitialPhaseBuilder<>(pipelineBuilder()); - } - - public <S> InitialPhaseBuilder<S> shouldBe(Class<S> cls, RBaseNode callObj, RError.Message message, Object... messageArgs) { - shouldBe(Predef.instanceOf(cls), callObj, message, messageArgs); - return new InitialPhaseBuilder<>(pipelineBuilder()); + return (InitialPhaseBuilder<S>) this; } public <S> InitialPhaseBuilder<S> shouldBe(Class<S> cls, RError.Message message, Object... messageArgs) { shouldBe(Predef.instanceOf(cls), message, messageArgs); - return new InitialPhaseBuilder<>(pipelineBuilder()); + return (InitialPhaseBuilder<S>) this; } public <S> InitialPhaseBuilder<S> shouldBe(Class<S> cls) { shouldBe(Predef.instanceOf(cls)); - return new InitialPhaseBuilder<>(pipelineBuilder()); + return (InitialPhaseBuilder<S>) this; } public <S> InitialPhaseBuilder<S> map(Mapper<T, S> mapFn) { pipelineBuilder().appendMap(mapFn); - return new InitialPhaseBuilder<>(pipelineBuilder()); + return (InitialPhaseBuilder<S>) this; } public InitialPhaseBuilder<Object> returnIf(Filter<? super T, ?> argFilter) { pipelineBuilder().appendMapIf(argFilter, (PipelineStep<?, ?>) null, (PipelineStep<?, ?>) null, true); - return new InitialPhaseBuilder<>(pipelineBuilder()); + return (InitialPhaseBuilder<Object>) this; } - public <S extends T, R> InitialPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper) { + public <S extends T, R> InitialPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, Mapper<? super S, R> trueBranchMapper) { pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, false); - return new InitialPhaseBuilder<>(pipelineBuilder()); + return (InitialPhaseBuilder<Object>) this; } - public <S extends T, R> InitialPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper) { + public <S extends T, R> InitialPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, Mapper<? super S, R> trueBranchMapper) { pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, true); - return new InitialPhaseBuilder<>(pipelineBuilder()); + return (InitialPhaseBuilder<Object>) this; } - public <S extends T, R> InitialPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper, Mapper<T, ?> falseBranchMapper) { + public <S extends T, R> InitialPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, Mapper<? super S, R> trueBranchMapper, Mapper<? super T, ?> falseBranchMapper) { pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, falseBranchMapper, false); - return new InitialPhaseBuilder<>(pipelineBuilder()); + return (InitialPhaseBuilder<Object>) this; } - public <S extends T, R> InitialPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper, Mapper<T, ?> falseBranchMapper) { + public <S extends T, R> InitialPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, Mapper<? super S, R> trueBranchMapper, Mapper<? super T, ?> falseBranchMapper) { pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, falseBranchMapper, true); - return new InitialPhaseBuilder<>(pipelineBuilder()); + return (InitialPhaseBuilder<Object>) this; } public <S extends T, R> InitialPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, PipelineStep<?, ?> trueBranch) { pipelineBuilder().appendMapIf(argFilter, trueBranch, false); - return new InitialPhaseBuilder<>(pipelineBuilder()); + return (InitialPhaseBuilder<Object>) this; } public <S extends T, R> InitialPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, PipelineStep<?, ?> trueBranch) { pipelineBuilder().appendMapIf(argFilter, trueBranch, true); - return new InitialPhaseBuilder<>(pipelineBuilder()); + return (InitialPhaseBuilder<Object>) this; } public <S extends T, R> InitialPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, PipelineStep<?, ?> trueBranch, PipelineStep<?, ?> falseBranch) { pipelineBuilder().appendMapIf(argFilter, trueBranch, falseBranch, false); - return new InitialPhaseBuilder<>(pipelineBuilder()); + return (InitialPhaseBuilder<Object>) this; } public <S extends T, R> InitialPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, PipelineStep<?, ?> trueBranch, PipelineStep<?, ?> falseBranch) { pipelineBuilder().appendMapIf(argFilter, trueBranch, falseBranch, true); - return new InitialPhaseBuilder<>(pipelineBuilder()); + return (InitialPhaseBuilder<Object>) this; } - public InitialPhaseBuilder<T> notNA(RBaseNode callObj, RError.Message message, Object... messageArgs) { - pipelineBuilder().appendNotNA(null, callObj, message, messageArgs); + public InitialPhaseBuilder<T> mustNotBeNA(RError.Message message, Object... messageArgs) { + pipelineBuilder().appendNotNA(null, message, messageArgs); return this; } - public InitialPhaseBuilder<T> notNA(RError.Message message, Object... messageArgs) { - pipelineBuilder().appendNotNA(null, null, message, messageArgs); + public InitialPhaseBuilder<T> shouldNotBeNA(T naReplacement, RError.Message message, Object... messageArgs) { + pipelineBuilder().appendNotNA(naReplacement, message, messageArgs); return this; } - public InitialPhaseBuilder<T> notNA(T naReplacement, RBaseNode callObj, RError.Message message, Object... messageArgs) { - pipelineBuilder().appendNotNA(naReplacement, callObj, message, messageArgs); - return this; - } - - public InitialPhaseBuilder<T> notNA(T naReplacement, RError.Message message, Object... messageArgs) { - pipelineBuilder().appendNotNA(naReplacement, null, message, messageArgs); - return this; - } - - public InitialPhaseBuilder<T> notNA(T naReplacement) { - pipelineBuilder().appendNotNA(naReplacement, null, null, null); + public InitialPhaseBuilder<T> replaceNA(T naReplacement) { + pipelineBuilder().appendNotNA(naReplacement, null, null); return this; } @@ -175,50 +151,26 @@ public class InitialPhaseBuilder<T> extends ArgCastBuilder<T, InitialPhaseBuilde } public CoercedPhaseBuilder<RAbstractIntVector, Integer> asIntegerVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - return asIntegerVector(preserveNames, preserveDimensions, preserveAttributes, null); - } - - public CoercedPhaseBuilder<RAbstractIntVector, Integer> asIntegerVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) { - pipelineBuilder().appendAsVector(RType.Integer, preserveNames, preserveDimensions, preserveAttributes, messageCallerObj); + pipelineBuilder().appendAsVector(RType.Integer, preserveNames, preserveDimensions, preserveAttributes); return new CoercedPhaseBuilder<>(pipelineBuilder(), Integer.class); } - public CoercedPhaseBuilder<RAbstractIntVector, Integer> asIntegerVector(RBaseNode messageCallerObj) { - return asIntegerVector(false, false, false, messageCallerObj); - } - public CoercedPhaseBuilder<RAbstractIntVector, Integer> asIntegerVector() { return asIntegerVector(false, false, false); } public CoercedPhaseBuilder<RAbstractDoubleVector, Double> asDoubleVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - return asDoubleVector(preserveNames, preserveDimensions, preserveAttributes, null); - } - - public CoercedPhaseBuilder<RAbstractDoubleVector, Double> asDoubleVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) { - pipelineBuilder().appendAsVector(RType.Double, preserveNames, preserveDimensions, preserveAttributes, messageCallerObj); + pipelineBuilder().appendAsVector(RType.Double, preserveNames, preserveDimensions, preserveAttributes); return new CoercedPhaseBuilder<>(pipelineBuilder(), Double.class); } - public CoercedPhaseBuilder<RAbstractDoubleVector, Double> asDoubleVector(RBaseNode messageCallerObj) { - return asDoubleVector(false, false, false, messageCallerObj); - } - public CoercedPhaseBuilder<RAbstractDoubleVector, Double> asDoubleVector() { return asDoubleVector(false, false, false); } - public CoercedPhaseBuilder<RAbstractLogicalVector, Byte> asLogicalVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) { - pipelineBuilder().appendAsVector(RType.Logical, preserveNames, preserveDimensions, preserveAttributes, messageCallerObj); - return new CoercedPhaseBuilder<>(pipelineBuilder(), Byte.class); - } - public CoercedPhaseBuilder<RAbstractLogicalVector, Byte> asLogicalVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - return asLogicalVector(preserveNames, preserveDimensions, preserveAttributes, null); - } - - public CoercedPhaseBuilder<RAbstractLogicalVector, Byte> asLogicalVector(RBaseNode messageCallerObj) { - return asLogicalVector(false, false, false, messageCallerObj); + pipelineBuilder().appendAsVector(RType.Logical, preserveNames, preserveDimensions, preserveAttributes); + return new CoercedPhaseBuilder<>(pipelineBuilder(), Byte.class); } public CoercedPhaseBuilder<RAbstractLogicalVector, Byte> asLogicalVector() { @@ -235,18 +187,10 @@ public class InitialPhaseBuilder<T> extends ArgCastBuilder<T, InitialPhaseBuilde } public CoercedPhaseBuilder<RAbstractComplexVector, RComplex> asComplexVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - return asComplexVector(preserveNames, preserveDimensions, preserveAttributes, null); - } - - public CoercedPhaseBuilder<RAbstractComplexVector, RComplex> asComplexVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) { - pipelineBuilder().appendAsVector(RType.Complex, preserveNames, preserveDimensions, preserveAttributes, messageCallerObj); + pipelineBuilder().appendAsVector(RType.Complex, preserveNames, preserveDimensions, preserveAttributes); return new CoercedPhaseBuilder<>(pipelineBuilder(), RComplex.class); } - public CoercedPhaseBuilder<RAbstractComplexVector, RComplex> asComplexVector(RBaseNode messageCallerObj) { - return asComplexVector(false, false, false, messageCallerObj); - } - public CoercedPhaseBuilder<RAbstractComplexVector, RComplex> asComplexVector() { return asComplexVector(false, false, false); } @@ -261,17 +205,17 @@ public class InitialPhaseBuilder<T> extends ArgCastBuilder<T, InitialPhaseBuilde } public CoercedPhaseBuilder<RAbstractVector, Object> asVector() { - pipelineBuilder().appendAsVector(false, false, false, true, null); + pipelineBuilder().appendAsVector(false, false, false, true); return new CoercedPhaseBuilder<>(pipelineBuilder(), Object.class); } public CoercedPhaseBuilder<RAbstractVector, Object> asVector(boolean preserveNonVector) { - pipelineBuilder().appendAsVector(false, false, false, preserveNonVector, null); + pipelineBuilder().appendAsVector(false, false, false, preserveNonVector); return new CoercedPhaseBuilder<>(pipelineBuilder(), Object.class); } public CoercedPhaseBuilder<RAbstractVector, Object> asVectorPreserveAttrs(boolean preserveNonVector) { - pipelineBuilder().appendAsVector(false, false, true, preserveNonVector, null); + pipelineBuilder().appendAsVector(false, false, true, preserveNonVector); return new CoercedPhaseBuilder<>(pipelineBuilder(), Object.class); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java index c5f4ba8394fb5725330bde49bc658ff886910af8..56374865240205f24e9b8a7a99656277ed34a29e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java @@ -22,17 +22,12 @@ */ package com.oracle.truffle.r.nodes.builtin.casts.fluent; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicReference; - import com.oracle.truffle.r.nodes.builtin.casts.Filter; import com.oracle.truffle.r.nodes.builtin.casts.Mapper; import com.oracle.truffle.r.nodes.builtin.casts.MessageData; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.AttributableCoercionStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep; -import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultErrorStep; -import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultWarningStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep; import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep; @@ -44,7 +39,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.analysis.ForwardingAnalysisResul import com.oracle.truffle.r.nodes.unary.CastNode; import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; /** * Class that holds the data for a pipeline for a single parameter. It holds the cast pipeline steps @@ -55,7 +49,7 @@ public final class PipelineBuilder { private final PipelineConfigBuilder pcb; private ChainBuilder<?> chainBuilder; - private final AtomicReference<Optional<ForwardingAnalysisResult>> fwdAnalysisResult = new AtomicReference<>(); + private volatile ForwardingAnalysisResult fwdAnalysisResult; public PipelineBuilder(String argumentName) { this.pcb = new PipelineConfigBuilder(argumentName); @@ -73,29 +67,25 @@ public final class PipelineBuilder { append(new PipelineStep.BoxPrimitiveStep<>()); } - public void appendFindFirst(Object defaultValue, Class<?> elementClass, RBaseNode callObj, Message message, Object[] messageArgs) { - append(new FindFirstStep<>(defaultValue, elementClass, createMessage(callObj, message, messageArgs))); + public void appendFindFirst(Object defaultValue, Class<?> elementClass, Message message, Object[] messageArgs) { + append(new FindFirstStep<>(defaultValue, elementClass, createMessage(message, messageArgs))); } public void appendAsAttributable(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { append(new AttributableCoercionStep<>(preserveNames, preserveDimensions, preserveAttributes)); } - public void appendAsVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean preserveNonVector, RBaseNode messageCallerObj) { - append(new CoercionStep<>(RType.Any, true, preserveNames, preserveDimensions, preserveAttributes, preserveNonVector, messageCallerObj)); - } - - public void appendAsVector(RType type, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) { - assert type == RType.Integer || type == RType.Double || type == RType.Complex || type == RType.Character || type == RType.Logical || type == RType.Raw; - append(new CoercionStep<>(type, true, preserveNames, preserveDimensions, preserveAttributes, true, messageCallerObj)); + public void appendAsVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean preserveNonVector) { + append(new CoercionStep<>(RType.Any, true, preserveNames, preserveDimensions, preserveAttributes, preserveNonVector)); } public void appendAsVector(RType type, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - appendAsVector(type, preserveNames, preserveDimensions, preserveAttributes, null); + assert type == RType.Integer || type == RType.Double || type == RType.Complex || type == RType.Character || type == RType.Logical || type == RType.Raw; + append(new CoercionStep<>(type, true, preserveNames, preserveDimensions, preserveAttributes, true)); } - public void appendNotNA(Object naReplacement, RBaseNode callObj, Message message, Object[] messageArgs) { - append(new NotNAStep<>(naReplacement, createMessage(callObj, message, messageArgs))); + public void appendNotNA(Object naReplacement, Message message, Object[] messageArgs) { + append(new NotNAStep<>(naReplacement, createMessage(message, messageArgs))); } public void appendMapIf(Filter<?, ?> argFilter, Mapper<?, ?> trueBranchMapper, boolean returns) { @@ -118,35 +108,23 @@ public final class PipelineBuilder { append(new MapStep<>(mapFn)); } - public void appendMustBeStep(Filter<?, ?> argFilter, RBaseNode callObj, Message message, Object[] messageArgs) { - append(new FilterStep<>(argFilter, createMessage(callObj, message, messageArgs), false)); + public void appendMustBeStep(Filter<?, ?> argFilter, Message message, Object[] messageArgs) { + append(new FilterStep<>(argFilter, createMessage(message, messageArgs), false)); } public void appendShouldBeStep(Filter<?, ?> argFilter, Message message, Object[] messageArgs) { - appendShouldBeStep(argFilter, null, message, messageArgs); - } - - public void appendShouldBeStep(Filter<?, ?> argFilter, RBaseNode callObj, Message message, Object[] messageArgs) { - append(new FilterStep<>(argFilter, createMessage(callObj, message, messageArgs), true)); + append(new FilterStep<>(argFilter, createMessage(message, messageArgs), true)); } - public void appendDefaultWarningStep(RBaseNode callObj, Message message, Object[] args) { - append(new DefaultWarningStep<>(createMessage(callObj, message, args))); - } - - public void appendDefaultErrorStep(RBaseNode callObj, Message message, Object[] args) { - append(new DefaultErrorStep<>(createMessage(callObj, message, args))); - } - - private static MessageData createMessage(RBaseNode callObj, Message message, Object[] messageArgs) { - return message == null ? null : new MessageData(callObj, message, messageArgs); + private static MessageData createMessage(Message message, Object[] messageArgs) { + return message == null ? null : new MessageData(message, messageArgs); } PipelineConfigBuilder getPipelineConfig() { return pcb; } - private PipelineStep<?, ?> getFirstStep() { + public PipelineStep<?, ?> getFirstStep() { return chainBuilder != null ? chainBuilder.getFirstStep() : null; } @@ -158,23 +136,19 @@ public final class PipelineBuilder { } } - public Optional<ForwardingAnalysisResult> getFwdAnalysisResult() { - Optional<ForwardingAnalysisResult> res = fwdAnalysisResult.get(); + public ForwardingAnalysisResult getFwdAnalysisResult() { + ForwardingAnalysisResult res = fwdAnalysisResult; if (res == null) { ForwardedValuesAnalyser fwdAnalyser = new ForwardedValuesAnalyser(); PipelineStep<?, ?> firstStep = getFirstStep(); if (firstStep == null) { - res = Optional.empty(); + res = ForwardingAnalysisResult.INVALID; } else { - res = Optional.of(fwdAnalyser.analyse(firstStep)); + res = fwdAnalyser.analyse(firstStep); } - if (fwdAnalysisResult.compareAndSet(null, res)) { - return res; - } else { - return fwdAnalysisResult.get(); - } - } else { - return res; + fwdAnalysisResult = res; } + assert res != null; + return res; } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineConfigBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineConfigBuilder.java index 2492ae892249550551e442523159521b161e828b..9fa3ffa3109970c15cc104782385cd2fe69235d6 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineConfigBuilder.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineConfigBuilder.java @@ -22,7 +22,6 @@ */ package com.oracle.truffle.r.nodes.builtin.casts.fluent; -import com.oracle.truffle.r.nodes.builtin.casts.Mapper; import com.oracle.truffle.r.nodes.builtin.casts.MessageData; import com.oracle.truffle.r.nodes.builtin.casts.PipelineConfig; import com.oracle.truffle.r.runtime.RError; @@ -39,20 +38,16 @@ public final class PipelineConfigBuilder { private MessageData defaultError; private MessageData defaultWarning; - private Mapper<? super RMissing, ?> missingMapper; - private Mapper<? super RNull, ?> nullMapper; - private MessageData missingMsg; - private MessageData nullMsg; private boolean valueForwarding = true; public PipelineConfigBuilder(String argumentName) { this.argumentName = argumentName; - defaultError = new MessageData(null, RError.Message.INVALID_ARGUMENT, argumentName); + defaultError = new MessageData(RError.Message.INVALID_ARGUMENT, argumentName); defaultWarning = defaultError; } public PipelineConfig build() { - return new PipelineConfig(argumentName, defaultError, defaultWarning, missingMapper, nullMapper, valueForwarding, missingMsg, nullMsg); + return new PipelineConfig(argumentName, defaultError, defaultWarning, valueForwarding); } void setDefaultError(MessageData defaultError) { @@ -67,5 +62,4 @@ public final class PipelineConfigBuilder { this.valueForwarding = flag; return this; } - } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java index 8cd3486523dfaf7d8e516ec507601aa45159a7cd..3c959e0bb414bd8e34556e3c3ebfff77377daf82 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java @@ -25,19 +25,16 @@ package com.oracle.truffle.r.nodes.builtin.casts.fluent; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; -import java.util.function.Consumer; - import com.oracle.truffle.r.nodes.builtin.casts.Mapper; import com.oracle.truffle.r.nodes.builtin.casts.MessageData; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; /** * Adds methods to {@link InitialPhaseBuilder} that allow to set up the pipeline configuration. - * Invocation of some methods means that the pre-initilization phase has been finishes, i.e. + * Invocation of some methods means that the pre-initialization phase has been finishes, i.e. * pipeline fully configured, those methods return this object cast to {@link InitialPhaseBuilder} * so that user then cannot invoke methods that change the pipeline configuration. Any method from * {@link InitialPhaseBuilder} returns that type, so once the user steps outside the configuration, @@ -49,72 +46,58 @@ public final class PreinitialPhaseBuilder extends InitialPhaseBuilder<Object> { super(pipelineBuilder); } - public PreinitialPhaseBuilder conf(Consumer<PipelineConfigBuilder> cfgLambda) { - cfgLambda.accept(pipelineBuilder().getPipelineConfig()); + public PreinitialPhaseBuilder allowNull() { + returnIf(nullValue()); return this; } - public InitialPhaseBuilder<Object> allowNull() { - return returnIf(nullValue()); - } - - public InitialPhaseBuilder<Object> mustNotBeNull() { - return mustBe(nullValue().not()); - } - - public InitialPhaseBuilder<Object> mustNotBeNull(RError.Message errorMsg, Object... msgArgs) { - return mustBe(nullValue().not(), null, errorMsg, msgArgs); - } - - public InitialPhaseBuilder<Object> mustNotBeNull(RBaseNode callObj, RError.Message errorMsg, Object... msgArgs) { - return mustBe(nullValue().not(), callObj, errorMsg, msgArgs); - } - - public InitialPhaseBuilder<Object> mapNull(Mapper<RNull, ?> mapper) { - return mapIf(nullValue(), mapper); + public PreinitialPhaseBuilder mustNotBeNull() { + mustBe(nullValue().not()); + return this; } - public InitialPhaseBuilder<Object> allowMissing() { - return returnIf(missingValue()); + public PreinitialPhaseBuilder mustNotBeNull(RError.Message errorMsg, Object... msgArgs) { + mustBe(nullValue().not(), errorMsg, msgArgs); + return this; } - public InitialPhaseBuilder<Object> mustNotBeMissing() { - return mustBe(missingValue().not()); + public PreinitialPhaseBuilder mapNull(Mapper<RNull, ?> mapper) { + mapIf(nullValue(), mapper); + return this; } - public InitialPhaseBuilder<Object> mustNotBeMissing(RError.Message errorMsg, Object... msgArgs) { - return mustBe(missingValue().not(), null, errorMsg, msgArgs); + public PreinitialPhaseBuilder allowMissing() { + returnIf(missingValue()); + return this; } - public InitialPhaseBuilder<Object> mustNotBeMissing(RBaseNode callObj, RError.Message errorMsg, Object... msgArgs) { - return mustBe(missingValue().not(), callObj, errorMsg, msgArgs); + public PreinitialPhaseBuilder mustNotBeMissing() { + mustBe(missingValue().not()); + return this; } - public InitialPhaseBuilder<Object> mapMissing(Mapper<RMissing, ?> mapper) { - return mapIf(missingValue(), mapper); + public PreinitialPhaseBuilder mustNotBeMissing(RError.Message errorMsg, Object... msgArgs) { + mustBe(missingValue().not(), errorMsg, msgArgs); + return this; } - public InitialPhaseBuilder<Object> allowNullAndMissing() { - return returnIf(nullValue().or(missingValue())); + public PreinitialPhaseBuilder mapMissing(Mapper<RMissing, ?> mapper) { + mapIf(missingValue(), mapper); + return this; } - @Override - public PreinitialPhaseBuilder defaultError(RBaseNode callObj, RError.Message message, Object... args) { - pipelineBuilder().getPipelineConfig().setDefaultError(new MessageData(callObj, message, args)); - pipelineBuilder().appendDefaultErrorStep(callObj, message, args); + public PreinitialPhaseBuilder allowNullAndMissing() { + returnIf(nullValue().or(missingValue())); return this; } - @Override - public PreinitialPhaseBuilder defaultError(Message message, Object... args) { - defaultError(null, message, args); + public PreinitialPhaseBuilder defaultError(RError.Message message, Object... args) { + pipelineBuilder().getPipelineConfig().setDefaultError(new MessageData(message, args)); return this; } - @Override - public PreinitialPhaseBuilder defaultWarning(RBaseNode callObj, Message message, Object... args) { - pipelineBuilder().getPipelineConfig().setDefaultWarning(new MessageData(callObj, message, args)); - pipelineBuilder().appendDefaultWarningStep(callObj, message, args); + public PreinitialPhaseBuilder defaultWarning(Message message, Object... args) { + pipelineBuilder().getPipelineConfig().setDefaultWarning(new MessageData(message, args)); return this; } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/BlockNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/BlockNode.java index e660d18e3c5dc08dcf48a1edb26d8e763ac58937..3feff83c7a6b2e77446cb91bc971fb81512d627a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/BlockNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/BlockNode.java @@ -76,12 +76,12 @@ public final class BlockNode extends OperatorNode { @Override @ExplodeLoop public Object visibleExecute(VirtualFrame frame) { - if (visibility == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - visibility = insert(SetVisibilityNode.create()); - } - visibility.execute(frame, true); if (sequence.length == 0) { + if (visibility == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + visibility = insert(SetVisibilityNode.create()); + } + visibility.execute(frame, true); return RNull.instance; } for (int i = 0; i < sequence.length - 1; i++) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java index 51d90997a825da38859ae982d9ed74496041004b..064888fb244ae0e45205bab0e42347d81f41fa88 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java @@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.control; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.instrumentation.InstrumentableFactory.WrapperNode; import com.oracle.truffle.api.nodes.LoopNode; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RepeatingNode; @@ -171,4 +172,16 @@ public final class ForNode extends AbstractLoopNode implements RSyntaxNode, RSyn public ArgumentsSignature getSyntaxSignature() { return ArgumentsSignature.empty(3); } + + /** + * Tests if the provided node is a loop-body node (also considering wrappers). + */ + public static boolean isLoopBody(Node n) { + Node parent = n.getParent(); + if (parent instanceof WrapperNode) { + Node grandparent = parent.getParent(); + return grandparent instanceof ForRepeatingNode && ((ForRepeatingNode) grandparent).body == parent; + } + return parent instanceof ForRepeatingNode && ((ForRepeatingNode) parent).body == n; + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/IfNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/IfNode.java index ae9a2cf35dcc7b6299139a3d68d44e23882a4827..d94fd6738db4ff5b74b58bb156ffe72737909d20 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/IfNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/IfNode.java @@ -57,7 +57,7 @@ public final class IfNode extends OperatorNode { byte cond = condition.executeByte(frame); if (cond == RRuntime.LOGICAL_NA) { CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.NA_UNEXP); + throw error(RError.Message.NA_UNEXP); } assert cond == RRuntime.LOGICAL_FALSE || cond == RRuntime.LOGICAL_TRUE : "logical value none of TRUE|FALSE|NA"; return conditionProfile.profile(cond == RRuntime.LOGICAL_TRUE); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/OperatorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/OperatorNode.java index 9a85a3d6f4c391e35186e9bc7be639f3f75ea92c..cf77ea161ca34f7627e0acbe2da1a1d14928c910 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/OperatorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/OperatorNode.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 @@ -23,6 +23,7 @@ package com.oracle.truffle.r.nodes.control; import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; @@ -41,4 +42,9 @@ public abstract class OperatorNode extends RSourceSectionNode implements RSyntax public final RSyntaxLookup getSyntaxLHS() { return operator; } + + @Override + protected RBaseNode getErrorContext() { + return this; + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java index 5eadedf9fbb67ac5f3fe35eb3889ffe541a8d4b9..cc06348a556c7376b626163fe3b21560b174c358 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java @@ -110,8 +110,7 @@ public final class ReplacementDispatchNode extends OperatorNode { if (c.getValue() instanceof String) { name = (String) c.getValue(); } else { - // "this" needs to be initialized for error reporting to work - throw RError.error(this, RError.Message.INVALID_LHS, "do_set"); + throw error(RError.Message.INVALID_LHS, "do_set"); } } else { throw RInternalError.unimplemented("unexpected lhs type in replacement: " + lhsSyntax.getClass()); @@ -144,9 +143,9 @@ public final class ReplacementDispatchNode extends OperatorNode { while (!(current instanceof RSyntaxLookup)) { if (!(current instanceof RSyntaxCall)) { if (current instanceof RSyntaxConstant && ((RSyntaxConstant) current).getValue() == RNull.instance) { - throw RError.error(this, RError.Message.INVALID_NULL_LHS); + throw error(RError.Message.INVALID_NULL_LHS); } else { - throw RError.error(this, RError.Message.NON_LANG_ASSIGNMENT_TARGET); + throw error(RError.Message.NON_LANG_ASSIGNMENT_TARGET); } } RSyntaxCall call = (RSyntaxCall) current; @@ -154,7 +153,7 @@ public final class ReplacementDispatchNode extends OperatorNode { RSyntaxElement syntaxLHS = call.getSyntaxLHS(); if (call.getSyntaxArguments().length == 0 || !(syntaxLHS instanceof RSyntaxLookup || isNamespaceLookupCall(syntaxLHS))) { - throw RError.error(this, RError.Message.INVALID_NULL_LHS); + throw error(RError.Message.INVALID_NULL_LHS); } current = call.getSyntaxArguments()[0]; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java index 5986bdbb7b83c5648cbb68104b43c0c942287f40..2eb77334c9d86cdb3b18af0e955c8b07a448931b 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java @@ -28,18 +28,16 @@ import java.util.List; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.source.SourceSection; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.nodes.access.RemoveAndAnswerNode; import com.oracle.truffle.r.nodes.access.WriteVariableNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.function.RCallSpecialNode; import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; -import com.oracle.truffle.r.nodes.unary.GetNonSharedNodeGen; +import com.oracle.truffle.r.nodes.unary.GetNonSharedNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.builtins.RSpecialFactory.FullCallNeededException; import com.oracle.truffle.r.runtime.context.RContext; @@ -53,7 +51,6 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) abstract class ReplacementNode extends OperatorNode { protected final RSyntaxElement lhs; @@ -63,6 +60,11 @@ abstract class ReplacementNode extends OperatorNode { this.lhs = lhs; } + @Override + public final Node deepCopy() { + return RContext.getASTBuilder().process(this).asRNode(); + } + public static ReplacementNode create(SourceSection source, RSyntaxLookup operator, RNode target, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls, String targetVarName, boolean isSuper, int tempNamesStartIndex, boolean isVoid) { CompilerAsserts.neverPartOfCompilation(); @@ -83,8 +85,12 @@ abstract class ReplacementNode extends OperatorNode { } } - private static String getTargetTmpName(int tempNamesStartIndex) { - return "*tmp*" + tempNamesStartIndex; + private static String getTargetTemp(int index) { + return "*tmp*" + index; + } + + private static String getRHSTemp(int index) { + return "*rhs*" + index; } private static boolean hasOnlySpecialCalls(List<RSyntaxCall> calls) { @@ -136,11 +142,6 @@ abstract class ReplacementNode extends OperatorNode { if (syntaxLHS instanceof RSyntaxLookup) { RSyntaxLookup lookupLHS = (RSyntaxLookup) syntaxLHS; String symbol = lookupLHS.getIdentifier(); - if ("slot".equals(symbol) || "@".equals(symbol)) { - // this is pretty gross, but at this point seems like the only way to get setClass - // to work properly - argNodes[0] = GetNonSharedNodeGen.create(argNodes[0].asRNode()); - } newSyntaxLHS = builder.lookup(lookupLHS.getLazySourceSection(), symbol + "<-", true); } else { // data types (and lengths) are verified in isNamespaceLookupCall @@ -149,7 +150,7 @@ abstract class ReplacementNode extends OperatorNode { RSyntaxNode[] newArgs = new RSyntaxNode[2]; newArgs[0] = (RSyntaxNode) oldArgs[0]; newArgs[1] = builder.lookup(oldArgs[1].getLazySourceSection(), ((RSyntaxLookup) oldArgs[1]).getIdentifier() + "<-", true); - newSyntaxLHS = RCallSpecialNode.createCall(callLHS.getLazySourceSection(), ((RSyntaxNode) callLHS.getSyntaxLHS()).asRNode(), callLHS.getSyntaxSignature(), newArgs); + newSyntaxLHS = RCallSpecialNode.createCall(callLHS.getLazySourceSection(), builder.process(callLHS.getSyntaxLHS(), codeBuilderContext).asRNode(), callLHS.getSyntaxSignature(), newArgs); } return RCallSpecialNode.createCallInReplace(source, newSyntaxLHS.asRNode(), ArgumentsSignature.get(names), argNodes, 0, argNodes.length - 1).asRNode(); } @@ -174,8 +175,8 @@ abstract class ReplacementNode extends OperatorNode { super(source, operator, lhs); this.rhs = rhs; - this.storeRhs = WriteVariableNode.createAnonymous("*rhs*" + tempNamesStartIndex, WriteVariableNode.Mode.INVISIBLE, rhs); - this.removeRhs = RemoveAndAnswerNode.create("*rhs*" + tempNamesStartIndex); + this.storeRhs = WriteVariableNode.createAnonymous(getRHSTemp(tempNamesStartIndex), WriteVariableNode.Mode.INVISIBLE, rhs); + this.removeRhs = RemoveAndAnswerNode.create(getRHSTemp(tempNamesStartIndex)); } @Override @@ -246,7 +247,7 @@ abstract class ReplacementNode extends OperatorNode { extractFunc = createSpecialFunctionQuery(calls.get(i), extractFunc.asRSyntaxNode(), codeBuilderContext); ((RCallSpecialNode) extractFunc).setPropagateFullCallNeededException(); } - this.replaceCall = (RCallSpecialNode) createFunctionUpdate(source, extractFunc.asRSyntaxNode(), ReadVariableNode.create("*rhs*" + tempNamesStartIndex), calls.get(0), codeBuilderContext); + this.replaceCall = (RCallSpecialNode) createFunctionUpdate(source, extractFunc.asRSyntaxNode(), ReadVariableNode.create(getRHSTemp(tempNamesStartIndex)), calls.get(0), codeBuilderContext); this.replaceCall.setPropagateFullCallNeededException(); } @@ -344,20 +345,22 @@ abstract class ReplacementNode extends OperatorNode { */ private static final class GenericReplacementNode extends ReplacementWithRhsNode { - @Child private WriteVariableNode targetTmpWrite; @Child private RemoveAndAnswerNode targetTmpRemove; - @Children private final RNode[] updates; + @Children private final WriteVariableNode[] updates; GenericReplacementNode(SourceSection source, RSyntaxLookup operator, RNode target, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls, String targetVarName, boolean isSuper, int tempNamesStartIndex) { - super(source, operator, lhs, rhs, tempNamesStartIndex); + super(source, operator, lhs, RContext.getASTBuilder().process(rhs.asRSyntaxNode()).asRNode(), tempNamesStartIndex); /* * When there are more than two function calls in LHS, then we save some function calls * by saving the intermediate results into temporary variables and reusing them. */ - List<RNode> instructions = new ArrayList<>(); + List<WriteVariableNode> instructions = new ArrayList<>(); CodeBuilderContext codeBuilderContext = new CodeBuilderContext(tempNamesStartIndex + calls.size() + 1); + + int targetIndex = tempNamesStartIndex; + instructions.add(WriteVariableNode.createAnonymous(getTargetTemp(targetIndex), WriteVariableNode.Mode.INVISIBLE, wrapForSlotUpdate(target, calls.get(calls.size() - 1)))); /* * Create the calls that extract inner components - only needed for complex replacements * like "a(b(x)) <- z" (where we would extract "b(x)"). The extracted values are saved @@ -365,35 +368,49 @@ abstract class ReplacementNode extends OperatorNode { * + calls.size()-1), the first such temporary variable holds the "target" of the * replacement, 'x' in our example (the assignment from 'x' is not done in this loop). */ - for (int i = calls.size() - 1, tmpIndex = 0; i >= 1; i--, tmpIndex++) { - ReadVariableNode newFirstArg = ReadVariableNode.create("*tmp*" + (tempNamesStartIndex + tmpIndex)); - RNode update = createSpecialFunctionQuery(calls.get(i), newFirstArg, codeBuilderContext); - instructions.add(WriteVariableNode.createAnonymous("*tmp*" + (tempNamesStartIndex + tmpIndex + 1), WriteVariableNode.Mode.INVISIBLE, update)); + for (int i = calls.size() - 1; i >= 1; i--) { + ReadVariableNode newFirstArg = ReadVariableNode.create(getTargetTemp(targetIndex)); + RNode extract = createSpecialFunctionQuery(calls.get(i), newFirstArg, codeBuilderContext); + instructions.add(WriteVariableNode.createAnonymous(getTargetTemp(++targetIndex), WriteVariableNode.Mode.INVISIBLE, wrapForSlotUpdate(extract, calls.get(i - 1)))); } /* * Create the update calls, for "a(b(x)) <- z", this would be `a<-` and `b<-`, the - * intermediate results are stored to temporary variables *tmpr*{index}. + * intermediate results are stored to temporary variables *rhs*{index}. */ + int replacementIndex = tempNamesStartIndex; for (int i = 0; i < calls.size(); i++) { - int tmpIndex = tempNamesStartIndex + calls.size() - i - 1; - String tmprName = i == 0 ? ("*rhs*" + tempNamesStartIndex) : ("*tmpr*" + (tempNamesStartIndex + i - 1)); - RNode update = createFunctionUpdate(source, ReadVariableNode.create("*tmp*" + tmpIndex), ReadVariableNode.create(tmprName), calls.get(i), codeBuilderContext); + RNode update = createFunctionUpdate(source, ReadVariableNode.create(getTargetTemp(targetIndex--)), ReadVariableNode.create(getRHSTemp(replacementIndex)), calls.get(i), + codeBuilderContext); if (i < calls.size() - 1) { - instructions.add(WriteVariableNode.createAnonymous("*tmpr*" + (tempNamesStartIndex + i), WriteVariableNode.Mode.INVISIBLE, update)); + instructions.add(WriteVariableNode.createAnonymous(getRHSTemp(++replacementIndex), WriteVariableNode.Mode.INVISIBLE, update)); } else { instructions.add(WriteVariableNode.createAnonymous(targetVarName, WriteVariableNode.Mode.REGULAR, update, isSuper)); } } - this.updates = instructions.toArray(new RNode[instructions.size()]); - this.targetTmpWrite = WriteVariableNode.createAnonymous(getTargetTmpName(tempNamesStartIndex), WriteVariableNode.Mode.INVISIBLE, target); - this.targetTmpRemove = RemoveAndAnswerNode.create(getTargetTmpName(tempNamesStartIndex)); + this.updates = instructions.toArray(new WriteVariableNode[instructions.size()]); + this.targetTmpRemove = RemoveAndAnswerNode.create(getTargetTemp(tempNamesStartIndex)); + } + + /* + * This is complicated, but at this point seems like the only way to get setClass to work + * properly. the underlying problem is that slot<- and @<- modify shared values, whereas, + * e.g., [[<- does not. + */ + private static RNode wrapForSlotUpdate(RNode target, RSyntaxCall call) { + RSyntaxElement syntaxLHS = call.getSyntaxLHS(); + if (syntaxLHS instanceof RSyntaxLookup) { + String symbol = ((RSyntaxLookup) syntaxLHS).getIdentifier(); + if ("slot".equals(symbol) || "@".equals(symbol)) { + return new GetNonSharedNode.GetNonSharedSyntaxNode(target); + } + } + return target; } @Override @ExplodeLoop protected void executeReplacement(VirtualFrame frame) { - targetTmpWrite.execute(frame); for (RNode update : updates) { update.execute(frame); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsCharNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsCharNode.java index 8f60448bc218234d188e7b2b0b017e328c04e7e0..60061c0032607c35d9bb9d413f1f574e08de8534 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsCharNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsCharNode.java @@ -30,12 +30,12 @@ import com.oracle.truffle.r.nodes.unary.CastStringNode; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RSymbol; -import com.oracle.truffle.r.runtime.data.RTypesFlatLayout; +import com.oracle.truffle.r.runtime.data.RTypes; import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper; -@TypeSystemReference(RTypesFlatLayout.class) +@TypeSystemReference(RTypes.class) public abstract class AsCharNode extends FFIUpCallNode.Arg1 { private static final CharSXPWrapper CharSXPWrapper_NA = CharSXPWrapper.create(RRuntime.STRING_NA); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsIntegerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsIntegerNode.java index a9cc0ef6bb481f6ea2e3e56148f86b71b03f123c..c37f801fcf001986b9046c2299d893bc25a020ba 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsIntegerNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsIntegerNode.java @@ -29,7 +29,7 @@ import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.r.nodes.unary.CastIntegerNode; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.RTypesFlatLayout; +import com.oracle.truffle.r.runtime.data.RTypes; import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; * Implements the {@code Rf_asInteger} GNU R function . The behavior is subtly different (more * permissive error-wise) that {@link CastIntegerNode}. Non-castable values return {@code NA}. */ -@TypeSystemReference(RTypesFlatLayout.class) +@TypeSystemReference(RTypes.class) public abstract class AsIntegerNode extends FFIUpCallNode.Arg1 { public abstract int execute(Object obj); @@ -90,5 +90,4 @@ public abstract class AsIntegerNode extends FFIUpCallNode.Arg1 { public static AsIntegerNode create() { return AsIntegerNodeGen.create(); } - } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java index b56d55b6e4a4d86cd99ffd88bdb5d93f003aad76..423574b4540ba6e6c920d63767f3fc7b3414d942 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java @@ -29,11 +29,11 @@ import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.r.nodes.unary.CastLogicalNode; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.RTypesFlatLayout; +import com.oracle.truffle.r.runtime.data.RTypes; import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -@TypeSystemReference(RTypesFlatLayout.class) +@TypeSystemReference(RTypes.class) public abstract class AsLogicalNode extends FFIUpCallNode.Arg1 { public abstract int execute(Object obj); @@ -54,7 +54,7 @@ public abstract class AsLogicalNode extends FFIUpCallNode.Arg1 { @Specialization(guards = "obj.getLength() > 0") protected int asLogical(RAbstractAtomicVector obj, @Cached("createNonPreserving()") CastLogicalNode castLogicalNode) { - Object castObj = castLogicalNode.execute(obj); + Object castObj = castLogicalNode.doCast(obj); if (castObj instanceof Byte) { return (byte) castObj; } else if (castObj instanceof RAbstractLogicalVector) { @@ -72,5 +72,4 @@ public abstract class AsLogicalNode extends FFIUpCallNode.Arg1 { public static AsLogicalNode create() { return AsLogicalNodeGen.create(); } - } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java index 0f977902306076282c0a669aa56fdbe7ee609505..b0667ef0480ec771cf76443bc0ab1cfb6e139c07 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java @@ -19,7 +19,7 @@ import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.r.nodes.unary.CastDoubleNode; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.RTypesFlatLayout; +import com.oracle.truffle.r.runtime.data.RTypes; import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @@ -29,7 +29,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; * subtly different (more permissive error-wise) that {@link CastDoubleNode}. Non-castable values * return {@code NA}. */ -@TypeSystemReference(RTypesFlatLayout.class) +@TypeSystemReference(RTypes.class) public abstract class AsRealNode extends FFIUpCallNode.Arg1 { public abstract double execute(Object obj); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/CoerceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/CoerceVectorNode.java index b7eb9d97d31188cc0fc7981ed94022e038561645..1d4729c310a374b1cb9fd78bb408e462241dfda2 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/CoerceVectorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/CoerceVectorNode.java @@ -55,24 +55,24 @@ public abstract class CoerceVectorNode extends FFIUpCallNode.Arg2 { } @Specialization(guards = "value.isS4()") - Object doS4Object(RTypedValue value, int mode) { + Object doS4Object(@SuppressWarnings("unused") RTypedValue value, @SuppressWarnings("unused") int mode) { throw RError.nyi(RError.NO_CALLER, "Rf_coerceVector for S4 objects."); } // Note: caches should cover all valid possibilities @Specialization(guards = {"!isS4Object(value)", "isNotList(value)", "isValidMode(mode)", "cachedMode == mode"}, limit = "99") - Object doCached(Object value, int mode, - @Cached("mode") int cachedMode, + Object doCached(Object value, @SuppressWarnings("unused") int mode, + @Cached("mode") @SuppressWarnings("unused") int cachedMode, @Cached("createCastNode(cachedMode)") CastNode castNode) { - return castNode.execute(value); + return castNode.doCast(value); } // Lists are coerced with only preserved names unlike other types @Specialization(guards = {"!isS4Object(value)", "isValidMode(mode)", "cachedMode == mode"}, limit = "99") - Object doCached(RList value, int mode, - @Cached("mode") int cachedMode, + Object doCached(RList value, @SuppressWarnings("unused") int mode, + @Cached("mode") @SuppressWarnings("unused") int cachedMode, @Cached("createCastNodeForList(cachedMode)") CastNode castNode) { - return castNode.execute(value); + return castNode.doCast(value); } @Fallback @@ -120,7 +120,7 @@ public abstract class CoerceVectorNode extends FFIUpCallNode.Arg2 { case VECSXP: return CastListNode.createForRFFI(true, forList, forList); case EXPRSXP: - return CastExpressionNode.createForRFFI(false, false, false); + return CastExpressionNode.createForRFFI(); case INTSXP: return CastIntegerNode.createForRFFI(true, preserveDims, preserveAttrs); case REALSXP: @@ -141,7 +141,7 @@ public abstract class CoerceVectorNode extends FFIUpCallNode.Arg2 { private static final class CastNullNode extends CastNode { @Override @TruffleBoundary - public Object execute(@SuppressWarnings("unused") Object value) { + public Object execute(Object value) { if (value instanceof RList) { throw RError.error(RError.NO_CALLER, Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, "list", "coerceVectorList"); } else { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java index e7d26f933bccbd58fc565b82df14d3dd87b84c0d..f1420a80ceb006a19d14f758496a16e642c608f3 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java @@ -35,6 +35,9 @@ import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CARNodeGen; import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CDDRNodeGen; import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CDRNodeGen; import com.oracle.truffle.r.nodes.ffi.MiscNodesFactory.LENGTHNodeGen; +import com.oracle.truffle.r.nodes.ffi.MiscNodesFactory.RDoNewObjectNodeGen; +import com.oracle.truffle.r.nodes.ffi.MiscNodesFactory.RDoSlotNodeGen; +import com.oracle.truffle.r.nodes.ffi.MiscNodesFactory.RDoSlotAssignNodeGen; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.context.RContext; @@ -44,6 +47,7 @@ public final class FFIUpCallRootNode extends RootNode { @Child private FFIUpCallNode theFFIUpCallNode; private final int numArgs; + @SuppressWarnings("deprecation") private FFIUpCallRootNode(FFIUpCallNode child) { super(RContext.getRRuntimeASTAccess().getTruffleRLanguage(), null, new FrameDescriptor()); theFFIUpCallNode = child; @@ -91,6 +95,9 @@ public final class FFIUpCallRootNode extends RootNode { FFIUpCallRootNode.add(RFFIUpCallMethod.CADDR, CADDRNodeGen::create); FFIUpCallRootNode.add(RFFIUpCallMethod.CDDR, CDDRNodeGen::create); FFIUpCallRootNode.add(RFFIUpCallMethod.LENGTH, LENGTHNodeGen::create); + FFIUpCallRootNode.add(RFFIUpCallMethod.R_do_new_object, RDoNewObjectNodeGen::create); + FFIUpCallRootNode.add(RFFIUpCallMethod.R_do_slot, RDoSlotNodeGen::create); + FFIUpCallRootNode.add(RFFIUpCallMethod.R_do_slot_assign, RDoSlotAssignNodeGen::create); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java index a12d923fd9d1eac96a6a53f5fe799a458d3abb74..a6e270047ddfc99e8f2ab0d7170fb53245a143d2 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java @@ -26,7 +26,12 @@ import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.guarantee; import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.guaranteeInstanceOf; import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.unimplemented; +import java.io.IOException; +import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -38,6 +43,7 @@ import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.nodes.RASTUtils; import com.oracle.truffle.r.nodes.ffi.ParseResult.ParseStatus; +import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RCleanUp; @@ -51,12 +57,14 @@ import com.oracle.truffle.r.runtime.RSrcref; import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.Utils; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.InvalidConnection; +import com.oracle.truffle.r.runtime.conn.NativeConnections.NativeRConnection; +import com.oracle.truffle.r.runtime.conn.RConnection; import com.oracle.truffle.r.runtime.context.Engine.ParseException; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RAttributesLayout; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RComplexVector; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDoubleSequence; import com.oracle.truffle.r.runtime.data.RDoubleVector; @@ -73,13 +81,20 @@ import com.oracle.truffle.r.runtime.data.RPairList; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RRaw; import com.oracle.truffle.r.runtime.data.RRawVector; -import com.oracle.truffle.r.runtime.data.RS4Object; import com.oracle.truffle.r.runtime.data.RSequence; import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.data.RUnboundValue; +import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +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.RAbstractListBaseVector; 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.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; @@ -107,6 +122,8 @@ import com.oracle.truffle.r.runtime.rng.RRNG; */ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { + private final Map<String, Object> nameSymbolCache = new ConcurrentHashMap<>(); + // Checkstyle: stop method name check @Override @@ -190,6 +207,11 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { return RContext.getEngine().evalFunction(getClass, null, RCaller.createInvalid(null), null, clazz); } + @Override + public Object R_do_new_object(Object classDef) { + return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.R_do_new_object).call(classDef); + } + @Override public Object Rf_findVar(Object symbolArg, Object envArg) { return findVarInFrameHelper(envArg, symbolArg, true); @@ -276,26 +298,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { } public static RStringVector getClassHr(Object v) { - RStringVector result; - if (v instanceof RAttributable) { - result = ((RAttributable) v).getClassHierarchy(); - } else if (v instanceof Byte) { - result = RLogicalVector.implicitClassHeader; - } else if (v instanceof String) { - result = RStringVector.implicitClassHeader; - } else if (v instanceof Integer) { - result = RIntVector.implicitClassHeader; - } else if (v instanceof Double) { - result = RDoubleVector.implicitClassHeader; - } else if (v instanceof RComplex) { - result = RComplexVector.implicitClassHeader; - } else if (v instanceof RRaw) { - result = RRawVector.implicitClassHeader; - } else { - guaranteeInstanceOf(v, RNull.class); - result = RNull.implicitClassHeader; - } - return result; + return ClassHierarchyNode.getClassHierarchy(v); } @Override @@ -312,7 +315,19 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { @Override public Object Rf_install(Object name) { - return RDataFactory.createSymbolInterned((String) name); + String nameStr = (String) name; + Object ret = nameSymbolCache.get(nameStr); + if (ret == null) { + ret = RDataFactory.createSymbolInterned(nameStr); + nameSymbolCache.put(nameStr, ret); + } + return ret; + } + + @Override + public Object Rf_installChar(Object name) { + CharSXPWrapper charSXP = guaranteeInstanceOf(name, CharSXPWrapper.class); + return RDataFactory.createSymbolInterned(charSXP.getContents()); } @Override @@ -356,7 +371,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { } @Override - public Object Rf_allocateVector(int mode, int n) { + public Object Rf_allocVector(int mode, int n) { SEXPTYPE type = SEXPTYPE.mapInt(mode); if (n < 0) { throw RError.error(RError.SHOW_CALLER2, RError.Message.NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED); @@ -370,7 +385,10 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { case LGLSXP: return RDataFactory.createLogicalVector(new byte[n], RDataFactory.COMPLETE_VECTOR); case STRSXP: - return RDataFactory.createStringVector(new String[n], RDataFactory.COMPLETE_VECTOR); + // fill list with empty strings + String[] data = new String[n]; + Arrays.fill(data, ""); + return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR); case CPLXSXP: return RDataFactory.createComplexVector(new double[2 * n], RDataFactory.COMPLETE_VECTOR); case RAWSXP: @@ -385,7 +403,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { } @Override - public Object Rf_allocateArray(int mode, Object dimsObj) { + public Object Rf_allocArray(int mode, Object dimsObj) { RIntVector dims = (RIntVector) dimsObj; int n = 1; int[] newDims = new int[dims.getLength()]; @@ -394,7 +412,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { newDims[i] = dims.getDataAt(i); n *= newDims[i]; } - RAbstractVector result = (RAbstractVector) Rf_allocateVector(mode, n); + RAbstractVector result = (RAbstractVector) Rf_allocVector(mode, n); setDims(newDims, result); return result; @@ -406,7 +424,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { } @Override - public Object Rf_allocateMatrix(int mode, int nrow, int ncol) { + public Object Rf_allocMatrix(int mode, int nrow, int ncol) { SEXPTYPE type = SEXPTYPE.mapInt(mode); if (nrow < 0 || ncol < 0) { throw RError.error(RError.SHOW_CALLER2, RError.Message.NEGATIVE_EXTENTS_TO_MATRIX); @@ -421,7 +439,9 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { case LGLSXP: return RDataFactory.createLogicalVector(new byte[nrow * ncol], RDataFactory.COMPLETE_VECTOR, dims); case STRSXP: - return RDataFactory.createStringVector(new String[nrow * ncol], RDataFactory.COMPLETE_VECTOR, dims); + String[] data = new String[nrow * ncol]; + Arrays.fill(data, ""); + return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR, dims); case CPLXSXP: return RDataFactory.createComplexVector(new double[2 * (nrow * ncol)], RDataFactory.COMPLETE_VECTOR, dims); default: @@ -574,14 +594,14 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { if (x instanceof RShareable) { return deep == 1 ? ((RShareable) x).deepCopy() : ((RShareable) x).copy(); } else if (x instanceof RSequence) { - return ((RSequence) x).materializeToShareable(); + return ((RSequence) x).materialize(); } else { return ((RExternalPtr) x).copy(); } } @Override - public int Rf_anyDuplicated(Object x, int fromLast) { + public int Rf_any_duplicated(Object x, int fromLast) { RAbstractVector vec = (RAbstractVector) x; if (vec.getLength() == 0) { return 0; @@ -727,7 +747,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { } @Override - public Object Rf_findfun(Object symbolObj, Object envObj) { + public Object Rf_findFun(Object symbolObj, Object envObj) { guarantee(envObj instanceof REnvironment); REnvironment env = (REnvironment) envObj; guarantee(symbolObj instanceof RSymbol); @@ -772,7 +792,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { } @Override - public int R_computeIdentical(Object x, Object y, int flags) { + public int R_compute_identical(Object x, Object y, int flags) { RFunction indenticalBuiltin = RContext.lookupBuiltin("identical"); Object res = RContext.getEngine().evalFunction(indenticalBuiltin, null, null, null, x, y, RRuntime.asLogical((!((flags & 1) == 0))), RRuntime.asLogical((!((flags & 2) == 0))), RRuntime.asLogical((!((flags & 4) == 0))), RRuntime.asLogical((!((flags & 8) == 0))), RRuntime.asLogical((!((flags & 16) == 0)))); @@ -780,13 +800,140 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { } @Override - public void Rf_copyListMatrix(Object s, Object t, int byrow) { + public void Rf_copyListMatrix(Object t, Object s, int byrow) { throw unimplemented(); } @Override - public void Rf_copyMatrix(Object s, Object t, int byrow) { - throw unimplemented(); + public void Rf_copyMatrix(Object t, Object s, int byRow) { + int tRows = RRuntime.nrows(t); + int tCols = RRuntime.ncols(t); + final Object sav = RRuntime.asAbstractVector(s); + ContainerItemCopier c; + if (sav instanceof RAbstractContainer) { + int sLen = ((RAbstractContainer) sav).getLength(); + if (sav instanceof RAbstractIntVector) { + c = new ContainerItemCopier() { + private final RAbstractIntVector sv = (RAbstractIntVector) sav; + private final RAbstractIntVector tv = (RAbstractIntVector) t; + private final Object tvStore = tv.getInternalStore(); + + @Override + public void copy(int sIdx, int tIdx) { + tv.setDataAt(tvStore, tIdx, sv.getDataAt(sIdx)); + } + }; + } else if (sav instanceof RAbstractDoubleVector) { + c = new ContainerItemCopier() { + private final RAbstractDoubleVector sv = (RAbstractDoubleVector) sav; + private final RAbstractDoubleVector tv = (RAbstractDoubleVector) t; + private final Object tvStore = tv.getInternalStore(); + + @Override + public void copy(int sIdx, int tIdx) { + tv.setDataAt(tvStore, tIdx, sv.getDataAt(sIdx)); + } + }; + } else if (sav instanceof RAbstractLogicalVector) { + c = new ContainerItemCopier() { + private final RAbstractLogicalVector sv = (RAbstractLogicalVector) sav; + private final RAbstractLogicalVector tv = (RAbstractLogicalVector) t; + private final Object tvStore = tv.getInternalStore(); + + @Override + public void copy(int sIdx, int tIdx) { + tv.setDataAt(tvStore, tIdx, sv.getDataAt(sIdx)); + } + }; + } else if (sav instanceof RAbstractComplexVector) { + c = new ContainerItemCopier() { + private final RAbstractComplexVector sv = (RAbstractComplexVector) sav; + private final RAbstractComplexVector tv = (RAbstractComplexVector) t; + private final Object tvStore = tv.getInternalStore(); + + @Override + public void copy(int sIdx, int tIdx) { + tv.setDataAt(tvStore, tIdx, sv.getDataAt(sIdx)); + } + }; + } else if (sav instanceof RAbstractStringVector) { + c = new ContainerItemCopier() { + private final RAbstractStringVector sv = (RAbstractStringVector) sav; + private final RAbstractStringVector tv = (RAbstractStringVector) t; + private final Object tvStore = tv.getInternalStore(); + + @Override + public void copy(int sIdx, int tIdx) { + tv.setDataAt(tvStore, tIdx, sv.getDataAt(sIdx)); + } + }; + } else if (sav instanceof RAbstractRawVector) { + c = new ContainerItemCopier() { + private final RAbstractRawVector sv = (RAbstractRawVector) sav; + private final RAbstractRawVector tv = (RAbstractRawVector) t; + private final Object tvStore = tv.getInternalStore(); + + @Override + public void copy(int sIdx, int tIdx) { + tv.setRawDataAt(tvStore, tIdx, sv.getRawDataAt(sIdx)); + } + }; + } else if (sav instanceof RAbstractListBaseVector) { + c = new ContainerItemCopier() { + private final RAbstractListBaseVector sv = (RAbstractListBaseVector) sav; + private final RAbstractListBaseVector tv = (RAbstractListBaseVector) t; + private final Object tvStore = tv.getInternalStore(); + + @Override + public void copy(int sIdx, int tIdx) { + tv.setDataAt(tvStore, tIdx, sv.getDataAt(sIdx)); + } + }; + } else { + throw unimplemented(); + } + if (byRow != 0) { + int sIdx = 0; + for (int i = 0; i < tRows; i++) { + int tIdx = i; + for (int j = 0; j < tCols; j++) { + c.copy(sIdx, tIdx); + sIdx++; + if (sIdx >= sLen) { + sIdx -= sLen; + } + tIdx += tRows; + } + } + } else { // Copy by column + int tLen = ((RAbstractContainer) t).getLength(); + if (sLen >= tLen) { + for (int i = 0; i < tLen; i++) { + c.copy(i, i); + } + } else { // Recycle needed + int sIdx = 0; + for (int i = 0; i < tLen; i++) { + c.copy(sIdx, i); + if (sIdx >= sLen) { + sIdx -= sLen; + } + } + } + } + + } else { // source is non-RAbstractContainer + throw unimplemented(); + } + } + + /** + * Helper interface for {@link #Rf_copyMatrix(java.lang.Object, java.lang.Object, int)} that + * copies from source index in an (internally held) source container into target index in a + * target container. + */ + interface ContainerItemCopier { + void copy(int sIdx, int tIdx); } @Override @@ -948,7 +1095,17 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { @Override public int IS_S4_OBJECT(Object x) { - return x instanceof RS4Object ? 1 : 0; + return ((x instanceof RTypedValue) && ((RTypedValue) x).isS4()) ? 1 : 0; + } + + @Override + public void SET_S4_OBJECT(Object x) { + guaranteeInstanceOf(x, RTypedValue.class).setS4(); + } + + @Override + public void UNSET_S4_OBJECT(Object x) { + guaranteeInstanceOf(x, RTypedValue.class).unsetS4(); } @Override @@ -1122,7 +1279,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { } @Override - public Object R_ExternalPtrProt(Object x) { + public Object R_ExternalPtrProtected(Object x) { RExternalPtr p = guaranteeInstanceOf(x, RExternalPtr.class); return p.getProt(); } @@ -1140,14 +1297,15 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { } @Override - public void R_SetExternalPtrProt(Object x, Object prot) { + public void R_SetExternalPtrProtected(Object x, Object prot) { RExternalPtr p = guaranteeInstanceOf(x, RExternalPtr.class); p.setProt(prot); } @Override - public REnvironment R_NewHashedEnv(REnvironment parent, int initialSize) { - REnvironment env = RDataFactory.createNewEnv(REnvironment.UNNAMED, true, initialSize); + public REnvironment R_NewHashedEnv(REnvironment parent, Object initialSize) { + // We know this is an RIntVector from use site in gramRd.c + REnvironment env = RDataFactory.createNewEnv(REnvironment.UNNAMED, true, ((RIntVector) initialSize).getDataAt(0)); RArguments.initializeEnclosingFrame(env.getFrame(), parent.getFrame()); return env; } @@ -1179,4 +1337,85 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { return RASTUtils.createLanguageElement(expr); } + @Override + public Object R_new_custom_connection(Object description, Object mode, Object className, Object connAddrObj) { + // TODO handle encoding properly ! + String strDescription = (String) description; + String strMode = (String) mode; + String strClassName = (String) className; + RExternalPtr connAddr = guaranteeInstanceOf(connAddrObj, RExternalPtr.class); + try { + return new NativeRConnection(strDescription, strMode, strClassName, connAddr).asVector(); + } catch (IOException e) { + return InvalidConnection.instance.asVector(); + } + } + + @Override + public int R_ReadConnection(int fd, byte[] buf) { + + try (BaseRConnection fromIndex = RConnection.fromIndex(fd)) { + Arrays.fill(buf, (byte) 0); + return fromIndex.readBin(ByteBuffer.wrap(buf)); + } catch (IOException e) { + throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_READING_CONNECTION, e.getMessage()); + } + } + + @Override + public int R_WriteConnection(int fd, byte[] buf) { + try (BaseRConnection fromIndex = RConnection.fromIndex(fd)) { + Arrays.fill(buf, (byte) 0); + final ByteBuffer wrapped = ByteBuffer.wrap(buf); + fromIndex.writeBin(wrapped); + return wrapped.position(); + } catch (IOException e) { + throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_WRITING_CONNECTION, e.getMessage()); + } + } + + @Override + public Object R_GetConnection(int fd) { + return RConnection.fromIndex(fd); + } + + @Override + public String getSummaryDescription(Object x) { + BaseRConnection conn = guaranteeInstanceOf(x, BaseRConnection.class); + return conn.getSummaryDescription(); + } + + @Override + public String getConnectionClassString(Object x) { + BaseRConnection conn = guaranteeInstanceOf(x, BaseRConnection.class); + return conn.getConnectionClass(); + } + + @Override + public String getOpenModeString(Object x) { + BaseRConnection conn = guaranteeInstanceOf(x, BaseRConnection.class); + return conn.getOpenMode().toString(); + } + + @Override + public boolean isSeekable(Object x) { + BaseRConnection conn = guaranteeInstanceOf(x, BaseRConnection.class); + return conn.isSeekable(); + } + + @Override + public Object R_do_slot(Object o, Object name) { + return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.R_do_slot).call(o, name); + } + + @Override + public Object R_do_slot_assign(Object o, Object name, Object value) { + return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.R_do_slot_assign).call(o, name, value); + } + + @Override + public Object R_MethodsNamespace() { + return REnvironment.getRegisteredNamespace("methods"); + } + } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ListAccessNodes.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ListAccessNodes.java index 1b443987e44dea159fc884aef156d3318affecdc..7dee1d0b06c9de3511c9f3ab681084f7ccc0fc0f 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ListAccessNodes.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ListAccessNodes.java @@ -29,7 +29,7 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RPairList; -import com.oracle.truffle.r.runtime.data.RTypesFlatLayout; +import com.oracle.truffle.r.runtime.data.RTypes; /** * Nodes that implement {@code CAR}, {@code CDR}, etc. N.B. GNU R does not error check the @@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.data.RTypesFlatLayout; */ public final class ListAccessNodes { - @TypeSystemReference(RTypesFlatLayout.class) + @TypeSystemReference(RTypes.class) public abstract static class CARNode extends FFIUpCallNode.Arg1 { @Specialization protected Object car(RPairList pl) { @@ -56,7 +56,7 @@ public final class ListAccessNodes { } - @TypeSystemReference(RTypesFlatLayout.class) + @TypeSystemReference(RTypes.class) public abstract static class CDRNode extends FFIUpCallNode.Arg1 { @Specialization protected Object cdr(RPairList pl) { @@ -76,7 +76,7 @@ public final class ListAccessNodes { } } - @TypeSystemReference(RTypesFlatLayout.class) + @TypeSystemReference(RTypes.class) public abstract static class CADRNode extends FFIUpCallNode.Arg1 { @Specialization protected Object cadr(RPairList pl) { @@ -95,7 +95,7 @@ public final class ListAccessNodes { } - @TypeSystemReference(RTypesFlatLayout.class) + @TypeSystemReference(RTypes.class) public abstract static class CADDRNode extends FFIUpCallNode.Arg1 { @Specialization protected Object caddr(RPairList pl) { @@ -114,7 +114,7 @@ public final class ListAccessNodes { } - @TypeSystemReference(RTypesFlatLayout.class) + @TypeSystemReference(RTypes.class) public abstract static class CDDRNode extends FFIUpCallNode.Arg1 { @Specialization protected Object cddr(RPairList pl) { @@ -133,5 +133,4 @@ public final class ListAccessNodes { } } - } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java index 4d833e1641f64b7dc1614d2792ff47265f4cacee..1391299116903197c9cdc349a57006945a292988 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java @@ -26,16 +26,23 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.TypeSystemReference; +import com.oracle.truffle.r.nodes.access.AccessSlotNode; +import com.oracle.truffle.r.nodes.access.AccessSlotNodeGen; +import com.oracle.truffle.r.nodes.access.UpdateSlotNode; +import com.oracle.truffle.r.nodes.access.UpdateSlotNodeGen; +import com.oracle.truffle.r.nodes.objects.NewObject; +import com.oracle.truffle.r.nodes.objects.NewObjectNodeGen; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RTypesFlatLayout; +import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.data.RTypes; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper; import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; public final class MiscNodes { - @TypeSystemReference(RTypesFlatLayout.class) + @TypeSystemReference(RTypes.class) public abstract static class LENGTHNode extends FFIUpCallNode.Arg1 { @Specialization @@ -80,4 +87,63 @@ public final class MiscNodes { throw RError.error(RError.SHOW_CALLER2, RError.Message.LENGTH_MISAPPLIED, SEXPTYPE.gnuRTypeForObject(obj).name()); } } + + @TypeSystemReference(RTypes.class) + abstract static class RDoSlotNode extends FFIUpCallNode.Arg2 { + + @Child private AccessSlotNode accessSlotNode; + + RDoSlotNode() { + accessSlotNode = AccessSlotNodeGen.create(false); + } + + @Specialization + Object doSlot(Object o, RSymbol nameSym) { + return accessSlotNode.executeAccess(o, nameSym.getName()); + } + + @Fallback + Object doSlot(@SuppressWarnings("unused") Object o, Object name) { + throw RError.error(RError.SHOW_CALLER2, RError.Message.INVALID_ARGUMENT_OF_TYPE, "name", SEXPTYPE.gnuRTypeForObject(name).name()); + } + + } + + @TypeSystemReference(RTypes.class) + abstract static class RDoSlotAssignNode extends FFIUpCallNode.Arg3 { + + @Child private UpdateSlotNode updateSlotNode; + + RDoSlotAssignNode() { + updateSlotNode = UpdateSlotNodeGen.create(); + } + + @Specialization + Object doSlotAssign(Object o, String name, Object value) { + return updateSlotNode.executeUpdate(o, name, value); + } + + @Fallback + Object doSlot(@SuppressWarnings("unused") Object o, Object name, @SuppressWarnings("unused") Object value) { + throw RError.error(RError.SHOW_CALLER2, RError.Message.INVALID_ARGUMENT_OF_TYPE, "name", SEXPTYPE.gnuRTypeForObject(name).name()); + } + + } + + @TypeSystemReference(RTypes.class) + abstract static class RDoNewObjectNode extends FFIUpCallNode.Arg1 { + + @Child private NewObject newObjectNode; + + RDoNewObjectNode() { + newObjectNode = NewObjectNodeGen.create(); + } + + @Specialization + Object doNewObject(Object classDef) { + return newObjectNode.execute(classDef); + } + + } + } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java index a998220115fb7fa4aec65f56d40e8c6087f704ce..218f407e58ce9c011ad1f2ed260a191360236f0d 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java @@ -40,6 +40,8 @@ public enum RFFIUpCallMethod { GetRNGstate("() : void"), INTEGER("(object) : object"), IS_S4_OBJECT("(object) : sint32"), + SET_S4_OBJECT("(object) : void"), + UNSET_S4_OBJECT("(object) : void"), LENGTH("(object) : sint32"), LOGICAL("(object) : object"), NAMED("(object) : sint32"), @@ -60,24 +62,31 @@ public enum RFFIUpCallMethod { R_CHAR("(object) : object"), R_CleanUp("(sint32, sint32, sint32) : void"), R_ExternalPtrAddr("(object) : object"), - R_ExternalPtrProt("(object) : object"), + R_ExternalPtrProtected("(object) : object"), R_ExternalPtrTag("(object) : object"), R_FindNamespace("(object) : object"), + R_GetConnection("(sint32) : object"), R_GlobalContext("() : object"), R_GlobalEnv("() : object"), R_HomeDir("() : object"), R_Interactive("() : sint32"), R_MakeExternalPtr("(object, object, object) : object"), + R_MethodsNamespace("() : object"), R_NamespaceRegistry("() : object"), - R_NewHashedEnv("(object, sint32) : object"), + R_NewHashedEnv("(object, object) : object"), R_ParseVector("(object, sint32, object) : object"), R_PromiseExpr("(object) : object"), + R_ReadConnection("(sint32, object) : sint32"), R_SetExternalPtrAddr("(object, object) : void"), - R_SetExternalPtrProt("(object, object) : void"), + R_SetExternalPtrProtected("(object, object) : void"), R_SetExternalPtrTag("(object, object) : void"), R_ToplevelExec("() : object"), - R_computeIdentical("(object, object, sint32) : sint32"), - R_do_MAKE_CLASS("(pointer) : object"), + R_WriteConnection("(sint32, object) : sint32"), + R_compute_identical("(object, object, sint32) : sint32"), + R_do_MAKE_CLASS("(string) : object"), + R_do_new_object("(object) : object"), + R_do_slot("(object, object) : object"), + R_do_slot_assign("(object, object, object) : object"), R_getContextCall("(object) : object"), R_getContextEnv("(object) : object"), R_getContextFun("(object) : object"), @@ -88,6 +97,7 @@ public enum RFFIUpCallMethod { R_isEqual("(object, object) : sint32"), R_isGlobal("(object) : sint32"), R_lsInternal3("(object, sint32, sint32) : object"), + R_new_custom_connection("(string, string, string, object) : object"), R_tryEval("(object, object, object) : object"), Rf_GetOption1("(object) : object"), Rf_PairToVectorList("(object) : object"), @@ -95,10 +105,10 @@ public enum RFFIUpCallMethod { Rf_ScalarInteger("(sint32) : object"), Rf_ScalarLogical("(sint32) : object"), Rf_ScalarString("(object) : object"), - Rf_allocateArray("(sint32, object) : object"), - Rf_allocateMatrix("(sint32, sint32, sint32) : object"), - Rf_allocateVector("(sint32, sint32) : object"), - Rf_anyDuplicated("(object, sint32) : sint32"), + Rf_allocArray("(sint32, object) : object"), + Rf_allocMatrix("(sint32, sint32, sint32) : object"), + Rf_allocVector("(sint32, sint32) : object"), + Rf_any_duplicated("(object, sint32) : sint32"), Rf_asChar("(object) : object"), Rf_asInteger("(object) : sint32"), Rf_asLogical("(object) : sint32"), @@ -110,16 +120,17 @@ public enum RFFIUpCallMethod { Rf_copyMatrix("(object, object, sint32) : void"), Rf_defineVar("(object, object, object) : void"), Rf_duplicate("(object, sint32) : object"), - Rf_error("(pointer) : void"), + Rf_error("(string) : void"), Rf_eval("(object, object) : object"), Rf_findVar("(object, object) : object"), Rf_findVarInFrame("(object, object) : object"), Rf_findVarInFrame3("(object, object, sint32) : object"), - Rf_findfun("(object, object) : object"), + Rf_findFun("(object, object) : object"), Rf_getAttrib("(object, object) : object"), Rf_gsetVar("(object, object, object) : void"), - Rf_inherits("(pointer, object) : sint32"), - Rf_install("(pointer) : object"), + Rf_inherits("(string, object) : sint32"), + Rf_install("(string) : object"), + Rf_installChar("(object) : object"), Rf_isNull("(object) : sint32"), Rf_isString("(object) : sint32"), Rf_lengthgets("(object, sint32) : object"), @@ -127,9 +138,9 @@ public enum RFFIUpCallMethod { Rf_ncols("(object) : sint32"), Rf_nrows("(object) : sint32"), Rf_setAttrib("(object, object, object) : void"), - Rf_warning("(pointer) : void"), - Rf_warningcall("(object, pointer) : void"), - Rprintf("(pointer) : void"), + Rf_warning("(string) : void"), + Rf_warningcall("(object, string) : void"), + Rprintf("(string) : void"), SETCADR("(object, object) : object"), SETCAR("(object, object) : object"), SETCDR("(object, object) : object"), @@ -145,6 +156,10 @@ public enum RFFIUpCallMethod { TAG("(object) : object"), TYPEOF("(object) : sint32"), VECTOR_ELT("(object, sint32) : object"), + getConnectionClassString("(object) : object"), + getOpenModeString("(object) : object"), + getSummaryDescription("(object) : object"), + isSeekable("(object) : object"), unif_rand("() : double"); /** @@ -160,6 +175,7 @@ public enum RFFIUpCallMethod { for (RFFIUpCallMethod f : RFFIUpCallMethod.values()) { System.out.printf("#define %s_x %d\n", f.name(), f.ordinal()); } + System.out.printf("\n#define CALLBACK_TABLE_SIZE %d\n", RFFIUpCallMethod.values().length); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TracingUpCallsRFFIImpl.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TracingUpCallsRFFIImpl.java index fd78becb64849ad60a065a0da30db451b4d4ad15..2bf8a0d955c98ac8da791351f6bc146bde2e9ad7 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TracingUpCallsRFFIImpl.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TracingUpCallsRFFIImpl.java @@ -117,6 +117,12 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI { return delegate.R_do_MAKE_CLASS(clazz); } + @Override + public Object R_do_new_object(Object classDef) { + RFFIUtils.traceUpCall("R_do_new_object", classDef); + return delegate.R_do_new_object(classDef); + } + @Override public Object Rf_findVar(Object symbolArg, Object envArg) { RFFIUtils.traceUpCall("Rf_findVar", symbolArg, envArg); @@ -159,6 +165,12 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI { return delegate.Rf_install(name); } + @Override + public Object Rf_installChar(Object name) { + RFFIUtils.traceUpCall("Rf_installChar", name); + return delegate.Rf_installChar(name); + } + @Override public Object Rf_lengthgets(Object x, int newSize) { RFFIUtils.traceUpCall("Rf_lengthgets", x, newSize); @@ -202,21 +214,21 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI { } @Override - public Object Rf_allocateVector(int mode, int n) { + public Object Rf_allocVector(int mode, int n) { RFFIUtils.traceUpCall("Rf_allocateVector", mode, n); - return delegate.Rf_allocateVector(mode, n); + return delegate.Rf_allocVector(mode, n); } @Override - public Object Rf_allocateArray(int mode, Object dimsObj) { + public Object Rf_allocArray(int mode, Object dimsObj) { RFFIUtils.traceUpCall("Rf_allocateArray", mode, dimsObj); return null; } @Override - public Object Rf_allocateMatrix(int mode, int nrow, int ncol) { + public Object Rf_allocMatrix(int mode, int nrow, int ncol) { RFFIUtils.traceUpCall("Rf_allocateMatrix", mode, ncol, nrow); - return delegate.Rf_allocateMatrix(mode, nrow, ncol); + return delegate.Rf_allocMatrix(mode, nrow, ncol); } @Override @@ -316,9 +328,9 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI { } @Override - public int Rf_anyDuplicated(Object x, int fromLast) { + public int Rf_any_duplicated(Object x, int fromLast) { RFFIUtils.traceUpCall("Rf_anyDuplicated", x, fromLast); - return delegate.Rf_anyDuplicated(x, fromLast); + return delegate.Rf_any_duplicated(x, fromLast); } @Override @@ -418,9 +430,9 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI { } @Override - public Object Rf_findfun(Object symbolObj, Object envObj) { + public Object Rf_findFun(Object symbolObj, Object envObj) { RFFIUtils.traceUpCall("Rf_findfun", symbolObj, envObj); - return delegate.Rf_findfun(symbolObj, envObj); + return delegate.Rf_findFun(symbolObj, envObj); } @Override @@ -442,9 +454,9 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI { } @Override - public int R_computeIdentical(Object x, Object y, int flags) { + public int R_compute_identical(Object x, Object y, int flags) { RFFIUtils.traceUpCall("R_computeIdentical", x, y, flags); - return delegate.R_computeIdentical(x, y, flags); + return delegate.R_compute_identical(x, y, flags); } @Override @@ -573,6 +585,18 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI { return delegate.IS_S4_OBJECT(x); } + @Override + public void SET_S4_OBJECT(Object x) { + RFFIUtils.traceUpCall("setS4Object"); + delegate.SET_S4_OBJECT(x); + } + + @Override + public void UNSET_S4_OBJECT(Object x) { + RFFIUtils.traceUpCall("unsetS4Object"); + delegate.UNSET_S4_OBJECT(x); + } + @Override public void Rprintf(Object message) { RFFIUtils.traceUpCall("Rprintf", message); @@ -676,9 +700,9 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI { } @Override - public Object R_ExternalPtrProt(Object x) { + public Object R_ExternalPtrProtected(Object x) { RFFIUtils.traceUpCall("R_ExternalPtrProt", x); - return delegate.R_ExternalPtrProt(x); + return delegate.R_ExternalPtrProtected(x); } @Override @@ -694,13 +718,13 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI { } @Override - public void R_SetExternalPtrProt(Object x, Object prot) { + public void R_SetExternalPtrProtected(Object x, Object prot) { RFFIUtils.traceUpCall("R_ExternalPtrProt", x); - delegate.R_SetExternalPtrProt(x, prot); + delegate.R_SetExternalPtrProtected(x, prot); } @Override - public REnvironment R_NewHashedEnv(REnvironment parent, int initialSize) { + public REnvironment R_NewHashedEnv(REnvironment parent, Object initialSize) { RFFIUtils.traceUpCall("R_NewHashedEnv", parent, initialSize); return delegate.R_NewHashedEnv(parent, initialSize); } @@ -735,4 +759,70 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI { return delegate.R_CHAR(x); } + @Override + public Object R_new_custom_connection(Object description, Object mode, Object className, Object readAddr) { + RFFIUtils.traceUpCall("R_new_custom_connection", description, mode, className, readAddr); + return delegate.R_new_custom_connection(description, mode, className, readAddr); + } + + @Override + public int R_ReadConnection(int fd, byte[] buf) { + RFFIUtils.traceUpCall("R_ReadConnection", fd, buf); + return delegate.R_ReadConnection(fd, buf); + } + + @Override + public int R_WriteConnection(int fd, byte[] buf) { + RFFIUtils.traceUpCall("R_WriteConnection", fd, buf); + return delegate.R_WriteConnection(fd, buf); + } + + @Override + public Object R_GetConnection(int fd) { + RFFIUtils.traceUpCall("R_GetConnection", fd); + return delegate.R_GetConnection(fd); + } + + @Override + public String getSummaryDescription(Object x) { + RFFIUtils.traceUpCall("getSummaryDescription", x); + return delegate.getSummaryDescription(x); + } + + @Override + public String getConnectionClassString(Object x) { + RFFIUtils.traceUpCall("getConnectionClassString", x); + return delegate.getConnectionClassString(x); + } + + @Override + public String getOpenModeString(Object x) { + RFFIUtils.traceUpCall("getOpenModeString", x); + return delegate.getOpenModeString(x); + } + + @Override + public boolean isSeekable(Object x) { + RFFIUtils.traceUpCall("isSeekable", x); + return delegate.isSeekable(x); + } + + @Override + public Object R_do_slot(Object o, Object name) { + RFFIUtils.traceUpCall("R_do_slot", o, name); + return delegate.R_do_slot(o, name); + } + + @Override + public Object R_do_slot_assign(Object o, Object name, Object value) { + RFFIUtils.traceUpCall("R_do_slot", o, name, value); + return delegate.R_do_slot_assign(o, name, value); + } + + @Override + public Object R_MethodsNamespace() { + RFFIUtils.traceUpCall("R_MethodsNamespace"); + return delegate.R_MethodsNamespace(); + } + } 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 30fc0680a855844113b4d879e6a786f60ed7dd7d..92e4c8dfa0d50926b61d8bc4fb57cf5097917278 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 @@ -31,6 +31,7 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotTypeException; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.Node; @@ -42,6 +43,7 @@ import com.oracle.truffle.r.runtime.Arguments; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RArguments.S3DefaultArguments; +import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; @@ -57,6 +59,7 @@ import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RPromise.Closure; import com.oracle.truffle.r.runtime.data.RPromise.PromiseState; import com.oracle.truffle.r.runtime.data.RPromise.RPromiseFactory; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RNode; @@ -211,10 +214,10 @@ public class ArgumentMatcher { } /** - * Used for the implementation of the 'UseMethod' builtin. Reorders the arguments passed into - * the called, generic function and prepares them to be passed into the specific function + * Used for matching varargs to an internally defined signature. Reorders the arguments passed + * into the called, generic function and prepares them to be passed into the specific function * - * @param target The 'Method' which is going to be 'Use'd + * @param formals The formal arguments to match to. * @param evaluatedArgs The arguments which are already in evaluated form (as they are directly * taken from the stack) * @param s3DefaultArguments default values carried over from S3 group dispatch method (e.g. @@ -223,8 +226,7 @@ public class ArgumentMatcher { * @return A Fresh {@link RArgsValuesAndNames} containing the arguments rearranged and stuffed * with default values (in the form of {@link RPromise}s where needed) */ - public static RArgsValuesAndNames matchArgumentsEvaluated(RRootNode target, RArgsValuesAndNames evaluatedArgs, S3DefaultArguments s3DefaultArguments, RBaseNode callingNode) { - FormalArguments formals = target.getFormalArguments(); + public static RArgsValuesAndNames matchArgumentsEvaluated(FormalArguments formals, RArgsValuesAndNames evaluatedArgs, S3DefaultArguments s3DefaultArguments, RBaseNode callingNode) { MatchPermutation match = permuteArguments(evaluatedArgs.getSignature(), formals.getSignature(), callingNode, index -> { throw RInternalError.unimplemented("S3Dispatch should not have arg length mismatch"); }, index -> evaluatedArgs.getSignature().getName(index), null); @@ -261,23 +263,42 @@ public class ArgumentMatcher { return new RArgsValuesAndNames(evaledArgs, formals.getSignature()); } + /** + * Used for the implementation of the 'UseMethod' builtin. Reorders the arguments passed into + * the called, generic function and prepares them to be passed into the specific function + * + * @param target The 'Method' which is going to be 'Use'd + * @param evaluatedArgs The arguments which are already in evaluated form (as they are directly + * taken from the stack) + * @param s3DefaultArguments default values carried over from S3 group dispatch method (e.g. + * from max to Summary.factor). {@code null} if there are no such arguments. + * @param callingNode The {@link Node} invoking the match + * @return A Fresh {@link RArgsValuesAndNames} containing the arguments rearranged and stuffed + * with default values (in the form of {@link RPromise}s where needed) + */ + public static RArgsValuesAndNames matchArgumentsEvaluated(RRootNode target, RArgsValuesAndNames evaluatedArgs, S3DefaultArguments s3DefaultArguments, RBaseNode callingNode) { + return matchArgumentsEvaluated(target.getFormalArguments(), evaluatedArgs, s3DefaultArguments, callingNode); + } + private static String getErrorForArgument(RNode[] suppliedArgs, ArgumentsSignature suppliedSignature, int index) { + CompilerAsserts.neverPartOfCompilation(); RNode node = suppliedArgs[index]; if (node instanceof VarArgNode) { CompilerAsserts.neverPartOfCompilation(); Frame frame = Utils.getActualCurrentFrame(); try { // TODO: this error handling code takes many assumptions about the argument types - RArgsValuesAndNames varArg = (RArgsValuesAndNames) frame.getObject(frame.getFrameDescriptor().findFrameSlot(ArgumentsSignature.VARARG_NAME)); + FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(ArgumentsSignature.VARARG_NAME); + RArgsValuesAndNames varArg = (RArgsValuesAndNames) FrameSlotChangeMonitor.getObject(frameSlot, frame); RPromise promise = (RPromise) varArg.getArguments()[((VarArgNode) node).getIndex()]; - return promise.getRep().asRSyntaxNode().getSourceSection().getCode(); + return RDeparse.deparseSyntaxElement(promise.getRep().asRSyntaxNode()); } catch (FrameSlotTypeException | ClassCastException e) { throw RInternalError.shouldNotReachHere(); } } else { String code; if (node.asRSyntaxNode().getSourceSection() != null) { - code = node.asRSyntaxNode().getSourceSection().getCode(); + code = RDeparse.deparseSyntaxElement(node.asRSyntaxNode()); } else { code = "<unknown>"; // RDeparse.deparseForPrint(node.asRSyntaxNode()); } @@ -545,7 +566,7 @@ public class ArgumentMatcher { } if (!matchedSuppliedArgs[suppliedIndex]) { String suppliedName = signature.getName(suppliedIndex); - if (suppliedName == null || suppliedName.isEmpty()) { + if (suppliedName == null || suppliedName.isEmpty() || formalSignature.getName(formalIndex).isEmpty()) { // unnamed parameter, match by position break; } @@ -600,7 +621,7 @@ public class ArgumentMatcher { // one unused argument CompilerDirectives.transferToInterpreter(); - throw RError.error(callingNode, RError.Message.UNUSED_ARGUMENT, errorString.apply(suppliedIndex)); + throw callingNode.error(RError.Message.UNUSED_ARGUMENT, errorString.apply(suppliedIndex)); } CompilerDirectives.transferToInterpreter(); @@ -615,7 +636,7 @@ public class ArgumentMatcher { str.append(errorString.apply(suppliedIndex)); } } - throw RError.error(callingNode, RError.Message.UNUSED_ARGUMENTS, str); + throw callingNode.error(RError.Message.UNUSED_ARGUMENTS, str); } return new MatchPermutation(resultPermutation, ArgumentsSignature.get(resultSignature), null, null); } @@ -661,7 +682,7 @@ public class ArgumentMatcher { return MatchPermutation.UNMATCHED; } else { // Has already been matched: Error! - throw RError.error(callingNode, RError.Message.FORMAL_MATCHED_MULTIPLE, formalName); + throw callingNode.error(RError.Message.FORMAL_MATCHED_MULTIPLE, formalName); } } return i; @@ -692,11 +713,11 @@ public class ArgumentMatcher { if (formalName.startsWith(suppliedName) && ((varArgIndex != ArgumentsSignature.NO_VARARG && i < varArgIndex) || varArgIndex == ArgumentsSignature.NO_VARARG)) { // partial-match only if the formal argument is positioned before ... if (found >= 0) { - throw RError.error(callingNode, RError.Message.ARGUMENT_MATCHES_MULTIPLE, 1 + suppliedIndex); + throw callingNode.error(RError.Message.ARGUMENT_MATCHES_MULTIPLE, 1 + suppliedIndex); } found = i; if (resultPermutation[found] != MatchPermutation.UNMATCHED) { - throw RError.error(callingNode, RError.Message.FORMAL_MATCHED_MULTIPLE, formalName); + throw callingNode.error(RError.Message.FORMAL_MATCHED_MULTIPLE, formalName); } } } @@ -704,6 +725,6 @@ public class ArgumentMatcher { if (found >= 0 || hasVarArgs) { return found; } - throw RError.error(callingNode, RError.Message.UNUSED_ARGUMENT, errorString.apply(suppliedIndex)); + throw callingNode.error(RError.Message.UNUSED_ARGUMENT, errorString.apply(suppliedIndex)); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java index b8ca65da53f800a50cdc6d44fa365abcfa257a3b..4c9b9aa0b6fbede742e9f3141231321d94a845b6 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.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 @@ -23,32 +23,31 @@ package com.oracle.truffle.r.nodes.function; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.dsl.TypeSystemReference; +import com.oracle.truffle.api.frame.FrameSlot; +import com.oracle.truffle.api.frame.FrameSlotKind; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; -import com.oracle.truffle.r.nodes.access.WriteLocalFrameVariableNode; import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.RArguments; -import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; /** * A {@link ArgumentStatePush} is used to bump up state transition for function arguments. */ -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) public abstract class ArgumentStatePush extends Node { public abstract void executeObject(VirtualFrame frame, Object shareable); - @Child private WriteLocalFrameVariableNode write; + @CompilationFinal private FrameSlot frameSlot; private final ConditionProfile isRefCountUpdateable = ConditionProfile.createBinaryProfile(); @@ -98,26 +97,24 @@ public abstract class ArgumentStatePush extends Node { if (isRefCountUpdateable.profile(!shareable.isSharedPermanent())) { shareable.incRefCount(); if (writeArgMask != -1 && !FastROptions.RefCountIncrementOnly.getBooleanValue()) { - if (write == null) { + if (frameSlot == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - write = insert(WriteLocalFrameVariableNode.createForRefCount(Integer.valueOf(writeArgMask))); + synchronized (FrameSlotChangeMonitor.class) { + frameSlot = frame.getFrameDescriptor().findOrAddFrameSlot(writeArgMask, FrameSlotKind.Object); + } } - write.execute(frame, shareable); + frame.setObject(frameSlot, shareable); } } } - @Specialization - public void transitionState(RShareable shareable) { - throw RInternalError.shouldNotReachHere("unexpected RShareable that is not RSharingAttributeStorage: " + shareable.getClass()); - } - @Specialization(guards = "!isShareable(o)") public void transitionStateNonShareable(@SuppressWarnings("unused") Object o) { // do nothing } protected boolean isShareable(Object o) { - return o instanceof RShareable; + RSharingAttributeStorage.verify(o); + return o instanceof RSharingAttributeStorage; } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java index fb29d87e3e6d63f2b2885f6156c62fb69c173861..cc46a97dbc6e04ef47e8496e7a2c0e8fcd874583 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.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 @@ -40,6 +40,7 @@ import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperN import com.oracle.truffle.r.runtime.Arguments; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RMissing; @@ -120,7 +121,7 @@ public final class CallArgumentsNode extends RBaseNode implements UnmatchedArgum CompilerAsserts.neverPartOfCompilation(); RArgsValuesAndNames varArgs = ReadVariableNode.lookupVarArgs(frame); if (varArgs == null) { - RError.error(RError.SHOW_CALLER, RError.Message.NO_DOT_DOT_DOT); + throw RError.error(RError.SHOW_CALLER, RError.Message.NO_DOT_DOT_DOT); } return varArgs; } @@ -233,7 +234,11 @@ public final class CallArgumentsNode extends RBaseNode implements UnmatchedArgum index = flattenVarArgsObject(frame, varArgs, values, index); vargsSymbolsIndex++; } else { - values[index] = arguments[i] == null ? RMissing.instance : arguments[i].execute(frame); + Object result = arguments[i] == null ? RMissing.instance : arguments[i].execute(frame); + if (CompilerDirectives.inInterpreter() && result == null) { + throw RInternalError.shouldNotReachHere("invalid null in arguments"); + } + values[index] = result; index++; } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java index ae7d5fc90258c04d53ef0a6fb87e310411e355b3..0e77db678e9fdab5a97ca7e600f8e50b192d17aa 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java @@ -29,7 +29,6 @@ import com.oracle.truffle.r.nodes.function.call.CallRFunctionCachedNodeGen; import com.oracle.truffle.r.nodes.function.call.CallRFunctionNode; import com.oracle.truffle.r.nodes.function.signature.VarArgsHelper; import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; -import com.oracle.truffle.r.nodes.unary.CastNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RArguments.DispatchArgs; @@ -187,7 +186,6 @@ public abstract class CallMatcherNode extends RBaseNode { @Child private CallMatcherNode next; @Child private CallRFunctionNode call; @Child private RBuiltinNode builtin; - @Children private final CastNode[] builtinArgumentCasts; @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); private final RBuiltinDescriptor builtinDescriptor; @@ -218,12 +216,10 @@ public abstract class CallMatcherNode extends RBaseNode { if (function.isBuiltin()) { this.builtinDescriptor = function.getRBuiltin(); this.builtin = RBuiltinNode.inline(builtinDescriptor); - this.builtinArgumentCasts = builtin.getCasts(); this.fastPath = null; this.fastPathVisibility = null; } else { this.call = CallRFunctionNode.create(function.getTarget()); - this.builtinArgumentCasts = null; this.builtinDescriptor = null; FastPathFactory fastPathFactory = root.getFastPath(); this.fastPath = fastPathFactory == null ? null : fastPathFactory.create(); @@ -231,6 +227,11 @@ public abstract class CallMatcherNode extends RBaseNode { } } + @Override + protected RBaseNode getErrorContext() { + return builtin == null ? super.getErrorContext() : builtin.getErrorContext(); + } + @Override public Object execute(VirtualFrame frame, ArgumentsSignature suppliedSignature, Object[] suppliedArguments, RFunction function, String functionName, DispatchArgs dispatchArgs) { if (suppliedSignature == cachedSuppliedSignature && function == cachedFunction && checkLastArgSignature(cachedSuppliedSignature, suppliedArguments)) { @@ -268,8 +269,7 @@ public abstract class CallMatcherNode extends RBaseNode { visibility.executeAfterCall(frame, caller); } } else { - applyCasts(reorderedArgs); - Object result = builtin.executeBuiltin(frame, reorderedArgs); + Object result = builtin.call(frame, reorderedArgs); visibility.execute(frame, builtinDescriptor.getVisibility()); return result; } @@ -278,16 +278,6 @@ public abstract class CallMatcherNode extends RBaseNode { } } - @ExplodeLoop - private void applyCasts(Object[] reorderedArgs) { - for (int i = 0; i < builtinArgumentCasts.length; i++) { - CastNode cast = builtinArgumentCasts[i]; - if (cast != null) { - reorderedArgs[i] = cast.execute(reorderedArgs[i]); - } - } - } - @Override @ExplodeLoop protected void replaceMissingArguments(RFunction function, Object[] args) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java index 3e3a70f6a376edeec50d7b697415317152945f19..29c1453ada068b616d66acff9b7c3d097a92095e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java @@ -27,12 +27,10 @@ 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.dsl.TypeSystemReference; 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.api.profiles.ValueProfile; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.nodes.RASTUtils; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode; @@ -40,30 +38,60 @@ import com.oracle.truffle.r.nodes.unary.CastToVectorNode; import com.oracle.truffle.r.nodes.unary.UnaryNode; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RAttributeStorage; import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RComplexVector; import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.REmpty; import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RIntVector; -import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RInteropScalar; import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RRaw; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RBaseNode; -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) public abstract class ClassHierarchyNode extends UnaryNode { + /** + * Returns the value of the {@code class} attribute or empty {@link RStringVector} if class + * attribute is not set. + */ + @TruffleBoundary + public static RStringVector getClassHierarchy(Object value) { + RStringVector result = null; + if (value instanceof RAttributable) { + Object v = ((RAttributable) value).getAttr(RRuntime.CLASS_ATTR_KEY); + result = v instanceof RStringVector ? (RStringVector) v : ImplicitClassHierarchyNode.getImplicitClass(value); + } + + return result != null ? result : RDataFactory.createEmptyStringVector(); + } + + /** + * Returns {@code true} if the {@code class} attribute is set to {@link RStringVector} whose + * first element equals to the given className. + */ + public static boolean hasClass(RAttributable value, String className) { + RStringVector v = getClassHierarchy(value); + for (int i = 0; i < v.getLength(); ++i) { + if (v.getDataAt(i).equals(className)) { + return true; + } + } + return false; + } + private static final RStringVector truffleObjectClassHeader = RDataFactory.createStringVectorFromScalar("truffle.object"); @Child private GetFixedAttributeNode access; @Child private S4Class s4Class; + @Child private ImplicitClassHierarchyNode implicit; private final boolean withImplicitTypes; private final boolean withS4; @@ -80,37 +108,55 @@ public abstract class ClassHierarchyNode extends UnaryNode { return ClassHierarchyNodeGen.create(false, false); } - @Override + public static ClassHierarchyNode createWithImplicit() { + return ClassHierarchyNodeGen.create(true, false); + } + public abstract RStringVector execute(Object arg); @Specialization protected RStringVector getClassHr(@SuppressWarnings("unused") byte arg) { - return withImplicitTypes ? RLogicalVector.implicitClassHeader : null; + return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Logical) : null; } @Specialization protected RStringVector getClassHr(@SuppressWarnings("unused") String arg) { - return withImplicitTypes ? RStringVector.implicitClassHeader : null; + return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Character) : null; } @Specialization protected RStringVector getClassHr(@SuppressWarnings("unused") int arg) { - return withImplicitTypes ? RIntVector.implicitClassHeader : null; + return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Integer) : null; } @Specialization protected RStringVector getClassHr(@SuppressWarnings("unused") double arg) { - return withImplicitTypes ? RDoubleVector.implicitClassHeader : null; + return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Double) : null; } @Specialization protected RStringVector getClassHr(@SuppressWarnings("unused") RComplex arg) { - return withImplicitTypes ? RComplexVector.implicitClassHeader : null; + return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Complex) : null; + } + + @Specialization + protected RStringVector getClassHr(@SuppressWarnings("unused") RRaw arg) { + return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Raw) : null; } @Specialization protected RStringVector getClassHr(@SuppressWarnings("unused") RNull arg) { - return withImplicitTypes ? RNull.implicitClassHeader : null; + return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Null) : null; + } + + @Specialization + protected RStringVector getClassHr(@SuppressWarnings("unused") RInteropScalar arg) { + return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(arg.getRType()) : null; + } + + @Specialization + protected RStringVector getClassHr(@SuppressWarnings("unused") REmpty arg) { + return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Null) : null; } @Specialization @@ -145,7 +191,15 @@ public abstract class ClassHierarchyNode extends UnaryNode { return classHierarchy; } } - return withImplicitTypes ? argProfile.profile(arg).getImplicitClass() : null; + if (withImplicitTypes) { + if (implicit == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + implicit = insert(ImplicitClassHierarchyNodeGen.create()); + } + return implicit.execute(arg); + } else { + return null; + } } protected static boolean isRTypedValue(Object obj) { @@ -165,6 +219,7 @@ public abstract class ClassHierarchyNode extends UnaryNode { @Fallback protected RStringVector getClassHr(Object obj) { + CompilerDirectives.transferToInterpreter(); throw RInternalError.shouldNotReachHere("type: " + (obj == null ? "null" : obj.getClass().getSimpleName())); } } @@ -185,7 +240,7 @@ abstract class S4Class extends RBaseNode { RFunction sExtendsForS3Function = ReadVariableNode.lookupFunction(".extendsForS3", methodsEnv.getFrame()); // the assumption here is that the R function can only return either a String or // RStringVector - s4Extends = (RStringVector) castToVector.execute( + s4Extends = (RStringVector) castToVector.doCast( RContext.getEngine().evalFunction(sExtendsForS3Function, methodsEnv.getFrame(), RCaller.create(null, RASTUtils.getOriginalCall(this)), null, classAttr)); RContext.getInstance().putS4Extends(classAttr, s4Extends); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyScalarNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyScalarNode.java index 8f47695a8a26ace0fbaad53e9cd6a8537e597eb2..53096fef441f0c9f0002d01b9a29ecf8909f290a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyScalarNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyScalarNode.java @@ -47,7 +47,7 @@ public abstract class ClassHierarchyScalarNode extends UnaryNode { Object v = RRuntime.asAbstractVector(arg); if (v instanceof RAttributable) { - RStringVector classHierarchy = ((RAttributable) v).getClassHierarchy(); + RStringVector classHierarchy = ClassHierarchyNode.getClassHierarchy((RAttributable) v); return classHierarchy.getLength() == 0 ? "" : classHierarchy.getDataAt(0); } else if (arg == RNull.instance) { return "NULL"; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java index 8ab60469026e8955106ad5d64b619bfa47097d21..8548f638ce166b419e5e26152f297b8e3685c486 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java @@ -68,6 +68,8 @@ import com.oracle.truffle.r.runtime.ReturnException; import com.oracle.truffle.r.runtime.Utils.DebugExitException; import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor; import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RPairList; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.env.frame.RFrameSlot; import com.oracle.truffle.r.runtime.nodes.RCodeBuilder; @@ -82,7 +84,10 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor; public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNode, RSyntaxFunction { - @Child private RNode body; // typed as RNode to avoid custom instrument wrapper + private final FormalArguments formalArguments; + + @Child private RNode body; + /** * This exists for debugging purposes. It is set initially when the function is defined to * either: @@ -135,7 +140,8 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo private FunctionDefinitionNode(SourceSection src, FrameDescriptor frameDesc, SourceSection[] argSourceSections, RNode saveArguments, RSyntaxNode body, FormalArguments formals, String name, PostProcessArgumentsNode argPostProcess) { - super(formals, frameDesc, RASTBuilder.createFunctionFastPath(body, formals.getSignature())); + super(frameDesc, RASTBuilder.createFunctionFastPath(body, formals.getSignature())); + this.formalArguments = formals; this.argSourceSections = argSourceSections; assert FrameSlotChangeMonitor.isValidFrameDescriptor(frameDesc); assert src != null; @@ -149,6 +155,16 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo this.argPostProcess = argPostProcess; } + @Override + public FormalArguments getFormalArguments() { + return formalArguments; + } + + @Override + public ArgumentsSignature getSignature() { + return formalArguments.getSignature(); + } + @Override public RootCallTarget duplicateWithNewFrameDescriptor() { RCodeBuilder<RSyntaxNode> builder = RContext.getASTBuilder(); @@ -253,6 +269,9 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo saveArguments.execute(frame); Object result = body.visibleExecute(frame); normalExit.enter(); + if (CompilerDirectives.inInterpreter() && result == null) { + throw RInternalError.shouldNotReachHere("invalid null in result of " + this); + } return result; } catch (ReturnException ex) { if (returnTopLevelProfile.profile(ex.getTarget() == RArguments.getCall(frame))) { @@ -296,18 +315,24 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo } if (runOnExitHandlers) { visibility.executeEndOfFunction(frame); - if (!noHandlerStackSlot.isValid() && frame.isObject(handlerStackSlot)) { - try { - RErrorHandling.restoreHandlerStack(frame.getObject(handlerStackSlot)); - } catch (FrameSlotTypeException e) { - throw RInternalError.shouldNotReachHere(); + if (!noHandlerStackSlot.isValid()) { + FrameSlot slot = getHandlerFrameSlot(frame); + if (frame.isObject(slot)) { + try { + RErrorHandling.restoreHandlerStack(frame.getObject(slot)); + } catch (FrameSlotTypeException e) { + throw RInternalError.shouldNotReachHere(); + } } } - if (!noRestartStackSlot.isValid() && frame.isObject(restartStackSlot)) { - try { - RErrorHandling.restoreRestartStack(frame.getObject(restartStackSlot)); - } catch (FrameSlotTypeException e) { - throw RInternalError.shouldNotReachHere(); + if (!noRestartStackSlot.isValid()) { + FrameSlot slot = getRestartFrameSlot(frame); + if (frame.isObject(slot)) { + try { + RErrorHandling.restoreRestartStack(frame.getObject(slot)); + } catch (FrameSlotTypeException e) { + throw RInternalError.shouldNotReachHere(); + } } } @@ -316,17 +341,26 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo CompilerDirectives.transferToInterpreterAndInvalidate(); onExitExpressionCache = insert(InlineCacheNode.createExpression(3)); } - ArrayList<Object> current = getCurrentOnExitList(frame, onExitSlot.executeFrameSlot(frame)); + RPairList current = getCurrentOnExitList(frame, onExitSlot.executeFrameSlot(frame)); /* * We do not need to preserve visibility, since visibility.executeEndOfFunction * was already called. */ - for (Object expr : current) { - if (!(expr instanceof RNode)) { - RInternalError.shouldNotReachHere("unexpected type for on.exit entry"); + try { + for (RPairList expr : current) { + if (expr.car() != RNull.instance) { + if (!(expr.car() instanceof RNode)) { + RInternalError.shouldNotReachHere("unexpected type for on.exit entry: " + expr.car()); + } + onExitExpressionCache.execute(frame, expr.car()); + } + } + } catch (ReturnException ex) { + if (returnTopLevelProfile.profile(ex.getTarget() == RArguments.getCall(frame))) { + return ex.getResult(); + } else { + throw ex; } - RNode node = (RNode) expr; - onExitExpressionCache.execute(frame, node); } } } @@ -418,10 +452,9 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo } } - @SuppressWarnings("unchecked") - private static ArrayList<Object> getCurrentOnExitList(VirtualFrame frame, FrameSlot slot) { + private static RPairList getCurrentOnExitList(VirtualFrame frame, FrameSlot slot) { try { - return (ArrayList<Object>) frame.getObject(slot); + return (RPairList) FrameSlotChangeMonitor.getObject(slot, frame); } catch (FrameSlotTypeException e) { throw RInternalError.shouldNotReachHere(); } @@ -481,20 +514,24 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo public FrameSlot getRestartFrameSlot(VirtualFrame frame) { if (noRestartStackSlot.isValid()) { CompilerDirectives.transferToInterpreterAndInvalidate(); - restartStackSlot = frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.RestartStack); noRestartStackSlot.invalidate(); } - assert restartStackSlot != null; + if (restartStackSlot == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + restartStackSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), RFrameSlot.RestartStack, FrameSlotKind.Object); + } return restartStackSlot; } public FrameSlot getHandlerFrameSlot(VirtualFrame frame) { if (noHandlerStackSlot.isValid()) { CompilerDirectives.transferToInterpreterAndInvalidate(); - handlerStackSlot = frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.HandlerStack); noHandlerStackSlot.invalidate(); } - assert handlerStackSlot != null; + if (handlerStackSlot == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + handlerStackSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), RFrameSlot.HandlerStack, FrameSlotKind.Object); + } return handlerStackSlot; } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionExpressionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionExpressionNode.java index cc6676d89f3499383915a05d82b9a91b50f5cb78..89977152e716fd5635345a5f2c46ad1ea0a5fce1 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionExpressionNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionExpressionNode.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 @@ -66,11 +66,6 @@ public final class FunctionExpressionNode extends RSourceSectionNode implements @Override public RFunction execute(VirtualFrame frame) { - return executeFunction(frame); - } - - @Override - public RFunction executeFunction(VirtualFrame frame) { visibility.execute(frame, true); MaterializedFrame matFrame = frame.materialize(); if (deoptFrameNode != null) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetMissingValueNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetMissingValueNode.java index 96c960da3eccb9c1917ceaf9452a349446b1c4de..d8cffeb8f5b1752ec8bb3c8018fcf76aa99b9353 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetMissingValueNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetMissingValueNode.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 @@ -29,6 +29,7 @@ import com.oracle.truffle.api.frame.FrameSlotTypeException; import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.nodes.NodeInfo; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.RBaseNode; /** @@ -78,7 +79,7 @@ public abstract class GetMissingValueNode extends RBaseNode { } if (isObjectProfile.profile(frame.isObject(slot))) { try { - return frame.getObject(slot); + return FrameSlotChangeMonitor.getObject(slot, frame); } catch (FrameSlotTypeException e) { return null; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ImplicitClassHierarchyNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ImplicitClassHierarchyNode.java new file mode 100644 index 0000000000000000000000000000000000000000..88e4949d7df687b0ce6a2ed613a15f299f2cf969 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ImplicitClassHierarchyNode.java @@ -0,0 +1,136 @@ +/* + * 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 + * 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.function; + +import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode; +import com.oracle.truffle.r.nodes.function.opt.ShareObjectNode; +import com.oracle.truffle.r.nodes.unary.UnaryNode; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.data.RAttributable; +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.RTypedValue; + +public abstract class ImplicitClassHierarchyNode extends UnaryNode { + + private static final RStringVector implicitArrayClass = ShareObjectNode.sharePermanent(RDataFactory.createStringVector("array")); + private static final RStringVector implicitMatrixClass = ShareObjectNode.sharePermanent(RDataFactory.createStringVector("matrix")); + @CompilationFinal(dimensions = 1) private static final RStringVector[] implicitClasses = new RStringVector[RType.values().length]; + + public static RStringVector getImplicitClass(RType type) { + RStringVector result = implicitClasses[type.ordinal()]; + if (result == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + implicitClasses[type.ordinal()] = result = ShareObjectNode.sharePermanent(RDataFactory.createStringVector(type.getClazz())); + } + return result; + } + + public abstract RStringVector execute(Object arg); + + @Specialization + protected static RStringVector get(@SuppressWarnings("unused") int value) { + return getImplicitClass(RType.Integer); + } + + @Specialization + protected static RStringVector get(@SuppressWarnings("unused") double value) { + return getImplicitClass(RType.Double); + } + + @Specialization + protected static RStringVector get(@SuppressWarnings("unused") String value) { + return getImplicitClass(RType.Character); + } + + @Specialization + protected static RStringVector get(@SuppressWarnings("unused") byte value) { + return getImplicitClass(RType.Logical); + } + + @Specialization(limit = "5", guards = "value.getClass() == valueClass") + protected static RStringVector getCachedClass(RTypedValue value, + @Cached("value.getClass()") Class<? extends RTypedValue> valueClass, + @Cached("createBinaryProfile()") ConditionProfile isArray, + @Cached("createBinaryProfile()") ConditionProfile isMatrix, + @Cached("create()") GetDimAttributeNode getDim) { + return getCachedType(value, valueClass.cast(value).getRType(), isArray, isMatrix, getDim); + } + + @Specialization(replaces = "getCachedClass", limit = "5", guards = "value.getRType() == type") + protected static RStringVector getCachedType(RTypedValue value, + @Cached("value.getRType()") RType type, + @Cached("createBinaryProfile()") ConditionProfile isArray, + @Cached("createBinaryProfile()") ConditionProfile isMatrix, + @Cached("create()") GetDimAttributeNode getDim) { + int[] dimensions = getDim.getDimensions(value); + if (isMatrix.profile(GetDimAttributeNode.isMatrix(dimensions))) { + return implicitMatrixClass; + } else if (isArray.profile(GetDimAttributeNode.isArray(dimensions))) { + return implicitArrayClass; + } else { + return getImplicitClass(type); + } + } + + @Specialization(replaces = {"getCachedClass", "getCachedType"}) + protected static RStringVector get(RTypedValue value, + @Cached("createBinaryProfile()") ConditionProfile isArray, + @Cached("createBinaryProfile()") ConditionProfile isMatrix, + @Cached("create()") GetDimAttributeNode getDim) { + return getCachedType(value, value.getRType(), isArray, isMatrix, getDim); + } + + public static RStringVector getImplicitClass(Object value) { + CompilerAsserts.neverPartOfCompilation(); + if (value instanceof Integer) { + return getImplicitClass(RType.Integer); + } else if (value instanceof Double) { + return getImplicitClass(RType.Double); + } else if (value instanceof String) { + return getImplicitClass(RType.Character); + } else if (value instanceof Byte) { + return getImplicitClass(RType.Logical); + } else if (value instanceof RAttributable) { + RAttributable attributable = (RAttributable) value; + RIntVector dim = (RIntVector) attributable.getAttr(RRuntime.DIM_ATTR_KEY); + if (dim != null) { + int[] dimArray = dim.getInternalStore(); + if (GetDimAttributeNode.isMatrix(dimArray)) { + return implicitMatrixClass; + } else if (GetDimAttributeNode.isArray(dimArray)) { + return implicitArrayClass; + } + } + } + return getImplicitClass(((RTypedValue) value).getRType()); + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.java index e808377fefc5bedf97ad147c5d5950c6cfbd272a..f5f59a4459e70de65e7f3d00295bd902071aef59 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.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 @@ -23,13 +23,18 @@ package com.oracle.truffle.r.nodes.function; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.frame.FrameSlot; +import com.oracle.truffle.api.frame.FrameSlotKind; +import com.oracle.truffle.api.frame.FrameSlotTypeException; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.utilities.AssumedValue; -import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; +import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RShareable; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.RNode; /** @@ -38,7 +43,7 @@ import com.oracle.truffle.r.runtime.nodes.RNode; */ public final class PostProcessArgumentsNode extends RNode { - @Children private final LocalReadVariableNode[] sequence; + @CompilationFinal(dimensions = 1) private final FrameSlot[] frameSlots; // stays the same during cloning private final AssumedValue<Integer> transArgsBitSet; @@ -47,7 +52,7 @@ public final class PostProcessArgumentsNode extends RNode { private final ConditionProfile isRefCountUpdateable = ConditionProfile.createBinaryProfile(); private PostProcessArgumentsNode(int length) { - this.sequence = new LocalReadVariableNode[Math.min(length, ArgumentStatePush.MAX_COUNTED_ARGS)]; + this.frameSlots = new FrameSlot[Math.min(length, ArgumentStatePush.MAX_COUNTED_ARGS)]; this.transArgsBitSet = new AssumedValue<>("PostProcessArgumentsNode.transArgsBitSet", 0); } @@ -56,7 +61,7 @@ public final class PostProcessArgumentsNode extends RNode { } public int getLength() { - return sequence.length; + return frameSlots.length; } @Override @@ -64,14 +69,21 @@ public final class PostProcessArgumentsNode extends RNode { public Object execute(VirtualFrame frame) { int bits = transArgsBitSet.get(); if (bits != 0) { - for (int i = 0; i < sequence.length; i++) { + for (int i = 0; i < frameSlots.length; i++) { int mask = 1 << i; if ((bits & mask) != 0) { - if (sequence[i] == null) { + if (frameSlots[i] == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - sequence[i] = insert(LocalReadVariableNode.create(Integer.valueOf(mask), false)); + synchronized (FrameSlotChangeMonitor.class) { + frameSlots[i] = frame.getFrameDescriptor().findOrAddFrameSlot(mask, FrameSlotKind.Object); + } + } + RShareable s; + try { + s = (RShareable) frame.getObject(frameSlots[i]); + } catch (FrameSlotTypeException e) { + throw RInternalError.shouldNotReachHere(); } - RShareable s = (RShareable) sequence[i].execute(frame); if (isNonNull.profile(s != null)) { if (isRefCountUpdateable.profile(!s.isSharedPermanent())) { s.decRefCount(); @@ -84,7 +96,7 @@ public final class PostProcessArgumentsNode extends RNode { } public boolean updateBits(int index) { - if (index < sequence.length) { + if (index < frameSlots.length) { int bits = transArgsBitSet.get(); int newBits = bits | (1 << index); if (newBits != bits) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java index 5dfa52418410ca0d58b3cfb489bd1219dfa09f80..b635984a2cb511bea0b9716cacf2003f3c1470ea 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java @@ -27,6 +27,7 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; import com.oracle.truffle.api.frame.FrameSlotTypeException; @@ -48,8 +49,9 @@ import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.VirtualEvalFrame; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise; -import com.oracle.truffle.r.runtime.data.RPromise.EagerPromiseBase; import com.oracle.truffle.r.runtime.data.RPromise.PromiseState; +import com.oracle.truffle.r.runtime.data.RShareable; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.RBaseNode; /** @@ -94,13 +96,13 @@ public class PromiseHelperNode extends RBaseNode { boolean deoptOne = false; for (FrameSlot slot : frame.getFrameDescriptor().getSlots().toArray(new FrameSlot[0])) { // We're only interested in RPromises - if (slot.getKind() != FrameSlotKind.Object) { + if (slot.getKind() != FrameSlotKind.Object || !(slot.getIdentifier() instanceof String)) { continue; } // Try to read it... try { - Object value = frame.getObject(slot); + Object value = FrameSlotChangeMonitor.getObject(slot, frame); // If it's a promise, deoptimize it! if (value instanceof RPromise) { @@ -120,7 +122,7 @@ public class PromiseHelperNode extends RBaseNode { private boolean deoptimize(RPromise promise) { if (!PromiseState.isDefaultOpt(promise.getState())) { deoptimizeProfile.enter(); - EagerPromiseBase eager = (EagerPromiseBase) promise; + EagerPromise eager = (EagerPromise) promise; return eager.deoptimize(); } @@ -155,7 +157,6 @@ public class PromiseHelperNode extends RBaseNode { return value; } - Object obj; int state = optStateProfile.profile(promise.getState()); if (PromiseState.isExplicit(state)) { CompilerDirectives.transferToInterpreter(); @@ -165,17 +166,9 @@ public class PromiseHelperNode extends RBaseNode { return evaluateSlowPath(frame, promise); } if (PromiseState.isDefaultOpt(state)) { - obj = generateValueDefault(frame, promise); - } else { - obj = generateValueEager(frame, state, (EagerPromiseBase) promise); - } - if (isEvaluated(promise)) { - // TODO: this only happens if compilation is in play and, as such, is difficult to track - // why (there is no obvious call path...) - return promise.getValue(); + return generateValueDefault(frame, promise); } else { - setValue(obj, promise); - return obj; + return generateValueNonDefault(frame, state, (EagerPromise) promise); } } @@ -190,28 +183,34 @@ public class PromiseHelperNode extends RBaseNode { promiseClosureCache = insert(InlineCacheNode.createPromise(FastROptions.PromiseCacheSize.getNonNegativeIntValue())); } promise.setUnderEvaluation(); - if (isInOriginFrame(frame, promise)) { - return promiseClosureCache.execute(frame, promise.getClosure()); - } else { - return promiseClosureCache.execute(wrapPromiseFrame(frame, promiseFrameProfile.profile(promise.getFrame())), promise.getClosure()); - } + Frame execFrame = isInOriginFrame(frame, promise) ? frame : wrapPromiseFrame(frame, promiseFrameProfile.profile(promise.getFrame())); + Object value = promiseClosureCache.execute(execFrame, promise.getClosure()); + assert promise.getRawValue() == null; + assert value != null; + promise.setValue(value); + return value; } finally { promise.resetUnderEvaluation(); } } - private Object generateValueEager(VirtualFrame frame, int state, EagerPromiseBase promise) { + private Object generateValueNonDefault(VirtualFrame frame, int state, EagerPromise promise) { assert !PromiseState.isDefaultOpt(state); if (!isDeoptimized(promise)) { Assumption eagerAssumption = isValidAssumptionProfile.profile(promise.getIsValidAssumption()); if (eagerAssumption.isValid()) { - if (!PromiseState.isEager(state)) { - RPromise nextPromise = (RPromise) promise.getEagerValue(); - return checkNextNode().evaluate(frame, nextPromise); - } else { + Object value; + if (PromiseState.isEager(state)) { assert PromiseState.isEager(state); - return getEagerValue(frame, (EagerPromise) promise); + value = getEagerValue(frame, promise); + } else { + RPromise nextPromise = (RPromise) promise.getEagerValue(); + value = checkNextNode().evaluate(frame, nextPromise); } + assert promise.getRawValue() == null; + assert value != null; + promise.setValue(value); + return value; } else { CompilerDirectives.transferToInterpreter(); promise.notifyFailure(); @@ -237,6 +236,16 @@ public class PromiseHelperNode extends RBaseNode { return promise.getValue(); } Object obj = generateValueDefaultSlowPath(frame, promise); + // if the value is temporary, we increment the reference count. The reason is that + // temporary values are considered available to be reused and altered (e.g. as a + // result of arithmetic operation), which is what we do not want to happen to a + // value that we are saving as the promise result. + if (obj instanceof RShareable) { + RShareable shareable = (RShareable) obj; + if (shareable.isTemporary()) { + shareable.incRefCount(); + } + } promise.setValue(obj); return obj; } @@ -246,7 +255,7 @@ public class PromiseHelperNode extends RBaseNode { // Evaluate guarded by underEvaluation obj = generateValueDefaultSlowPath(frame, promise); } else { - obj = generateValueEagerSlowPath(frame, state, (EagerPromiseBase) promise); + obj = generateValueEagerSlowPath(frame, state, (EagerPromise) promise); } promise.setValue(obj); return obj; @@ -275,7 +284,7 @@ public class PromiseHelperNode extends RBaseNode { return VirtualEvalFrame.create(promiseFrame, RArguments.getFunction(promiseFrame), RCaller.createForPromise(RArguments.getCall(promiseFrame), frame)); } - private static Object generateValueEagerSlowPath(VirtualFrame frame, int state, EagerPromiseBase promise) { + private static Object generateValueEagerSlowPath(VirtualFrame frame, int state, EagerPromise promise) { assert !PromiseState.isDefaultOpt(state); if (!promise.isDeoptimized()) { Assumption eagerAssumption = promise.getIsValidAssumption(); @@ -307,7 +316,7 @@ public class PromiseHelperNode extends RBaseNode { */ public void materialize(RPromise promise) { if (isDefaultOptProfile.profile(!PromiseState.isDefaultOpt(promise.getState()))) { - EagerPromiseBase eager = (EagerPromiseBase) promise; + EagerPromise eager = (EagerPromise) promise; eager.materialize(); } // otherwise: already the generic and slow RPromise @@ -325,7 +334,7 @@ public class PromiseHelperNode extends RBaseNode { return isNullFrameProfile.profile(promise.isNullFrame()); } - private boolean isDeoptimized(EagerPromiseBase promise) { + private boolean isDeoptimized(EagerPromise promise) { return isDeoptimizedProfile.profile(promise.isDeoptimized()); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java index 5bea3d00320ac04a6bc1ab5350ada52995c155a3..fb72a30e6767f4d7cfe16c7646084ecc216de57a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.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 @@ -32,7 +32,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.ExplodeLoop; -import com.oracle.truffle.api.nodes.UnexpectedResultException; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.source.SourceSection; @@ -44,8 +43,10 @@ import com.oracle.truffle.r.nodes.function.opt.OptConstantPromiseNode; import com.oracle.truffle.r.nodes.function.opt.OptForcedEagerPromiseNode; import com.oracle.truffle.r.nodes.function.opt.OptVariablePromiseBaseNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RPromise; @@ -294,13 +295,12 @@ public abstract class PromiseNode extends RNode { CompilerDirectives.transferToInterpreterAndInvalidate(); lookupVarArgs = insert(ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any)); } - RArgsValuesAndNames varArgsAndNames; - try { - varArgsAndNames = lookupVarArgs.executeRArgsValuesAndNames(frame); - } catch (UnexpectedResultException e) { - throw RInternalError.shouldNotReachHere(e, "'...' should always be represented by RArgsValuesAndNames"); + Object varArgs = lookupVarArgs.execute(frame); + if (!(varArgs instanceof RArgsValuesAndNames)) { + CompilerDirectives.transferToInterpreter(); + throw RError.error(RError.SHOW_CALLER, RError.Message.NO_DOT_DOT_DOT); } - return varArgsAndNames; + return (RArgsValuesAndNames) varArgs; } @Override @@ -335,7 +335,7 @@ public abstract class PromiseNode extends RNode { @TruffleBoundary public String getIdentifier() { int num = index + 1; - return (num < 10 ? ".." : ".") + num; + return Utils.intern((num < 10 ? ".." : ".") + num); } @Override diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNodeWrapperFactory.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNodeWrapperFactory.java index 6f6b94ab2207b80c9e339d717877e12440e43439..70d38d3f2926de903d95478bf63be2b43ed43aae 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNodeWrapperFactory.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNodeWrapperFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -66,6 +66,19 @@ public class RCallBaseNodeWrapperFactory implements InstrumentableFactory<RCallB } } + @Override + public Object visibleExecute(VirtualFrame frame) { + try { + probeNode.onEnter(frame); + Object returnValue = delegate.visibleExecute(frame); + probeNode.onReturnValue(frame, returnValue); + return returnValue; + } catch (Throwable t) { + probeNode.onReturnExceptional(frame, t); + throw t; + } + } + @Override public Object execute(VirtualFrame frame, Object function) { try { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java index 5c9497e41bdfb24bd5d4092800123fee1682d397..7fa4270828d46489c5babae16b4f34a4715714db 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java @@ -36,24 +36,23 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotTypeException; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.ArityException; 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.UnsupportedMessageException; +import com.oracle.truffle.api.interop.UnsupportedTypeException; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.nodes.NodeInfo; -import com.oracle.truffle.api.nodes.UnexpectedResultException; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.api.source.SourceSection; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.nodes.RASTUtils; import com.oracle.truffle.r.nodes.RRootNode; import com.oracle.truffle.r.nodes.access.ConstantNode; @@ -69,7 +68,6 @@ import com.oracle.truffle.r.nodes.function.call.PrepareArguments; import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode; import com.oracle.truffle.r.nodes.profile.VectorLengthProfile; -import com.oracle.truffle.r.nodes.unary.CastNode; import com.oracle.truffle.r.runtime.Arguments; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RArguments; @@ -89,14 +87,19 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor; import com.oracle.truffle.r.runtime.conn.RConnection; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RAttributeStorage; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.REmpty; 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.RPromise.Closure; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RTypedValue; +import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RFastPathNode; import com.oracle.truffle.r.runtime.nodes.RNode; @@ -105,7 +108,6 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) @NodeInfo(cost = NodeCost.NONE) @NodeChild(value = "function", type = RNode.class) public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RSyntaxCall { @@ -131,6 +133,11 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS return sourceSection; } + @Override + protected RBaseNode getErrorContext() { + return this; + } + public abstract RNode getFunction(); private final RSyntaxNode[] arguments; @@ -167,16 +174,6 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS this.explicitArgs = null; this.varArgIndexes = getVarArgIndexes(arguments); this.lookupVarArgs = varArgIndexes.length == 0 ? null : ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any); - - for (String name : signature) { - if (name != null && name.isEmpty()) { - /* - * In GnuR this is evidently output by the parser, so very early, and never with a - * caller in the message. - */ - throw RError.error(RError.NO_CALLER, RError.Message.ZERO_LENGTH_VARIABLE); - } - } this.signature = signature; } @@ -218,17 +215,16 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS if (explicitArgs != null) { return (RArgsValuesAndNames) explicitArgs.execute(frame); } - RArgsValuesAndNames varArgs; if (lookupVarArgs == null) { - varArgs = null; + return null; } else { - try { - varArgs = lookupVarArgs.executeRArgsValuesAndNames(frame); - } catch (UnexpectedResultException e) { + Object varArgs = lookupVarArgs.execute(frame); + if (!(varArgs instanceof RArgsValuesAndNames)) { + CompilerDirectives.transferToInterpreter(); throw RError.error(RError.SHOW_CALLER, RError.Message.NO_DOT_DOT_DOT); } + return (RArgsValuesAndNames) varArgs; } - return varArgs; } protected FunctionDispatch createUninitializedCall() { @@ -279,17 +275,36 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS @Cached("createWithError()") S3FunctionLookupNode dispatchLookup, @Cached("createIdentityProfile()") ValueProfile builtinProfile, @Cached("createBinaryProfile()") ConditionProfile implicitTypeProfile, + @Cached("createBinaryProfile()") ConditionProfile isAttributableProfile, @Cached("createBinaryProfile()") ConditionProfile resultIsBuiltinProfile, - @Cached("create()") GetBaseEnvFrameNode getBaseEnvFrameNode) { + @Cached("create()") GetBaseEnvFrameNode getBaseEnvFrameNode, + @Cached("createBinaryProfile()") ConditionProfile isS4Profile, + @Cached("new()") PromiseCheckHelperNode promiseHelper) { RBuiltinDescriptor builtin = builtinProfile.profile(function.getRBuiltin()); Object dispatchObject = dispatchArgument.execute(frame); // Cannot dispatch on REmpty if (dispatchObject == REmpty.instance) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.ARGUMENT_EMPTY, 1); + throw error(RError.Message.ARGUMENT_EMPTY, 1); } FrameSlot slot = dispatchTempSlot.initialize(frame, dispatchObject); try { + if (internalDispatchCall == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + internalDispatchCall = insert(FunctionDispatchNodeGen.create(this, false, slot)); + } + + if (isAttributableProfile.profile(dispatchObject instanceof RAttributeStorage) && isS4Profile.profile(((RAttributeStorage) dispatchObject).isS4())) { + RList list = (RList) promiseHelper.checkEvaluate(frame, REnvironment.getRegisteredNamespace("methods").get(".BasicFunsList")); + // TODO create a node that looksup the name in the names attribute + int index = list.getElementIndexByName(builtin.getName()); + if (index != -1) { + RFunction basicFun = (RFunction) list.getDataAt(index); + Object result = internalDispatchCall.execute(frame, basicFun, lookupVarArgs(frame), null, null); + if (result != RRuntime.DEFERRED_DEFAULT_MARKER) { + return result; + } + } + } RStringVector type = classHierarchyNode.execute(dispatchObject); S3Args s3Args; RFunction resultFunction; @@ -321,14 +336,31 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS @Cached("createWithError()") S3FunctionLookupNode dispatchLookup, @Cached("createIdentityProfile()") ValueProfile builtinProfile, @Cached("createBinaryProfile()") ConditionProfile implicitTypeProfile, + @Cached("createBinaryProfile()") ConditionProfile isAttributableProfile, @Cached("createBinaryProfile()") ConditionProfile resultIsBuiltinProfile, @Cached("createPromiseHelper()") PromiseCheckHelperNode promiseHelperNode, @Cached("createUninitializedExplicitCall()") FunctionDispatch call, + @Cached("createBinaryProfile()") ConditionProfile isS4Profile, @Cached("create()") GetBaseEnvFrameNode getBaseEnvFrameNode) { RBuiltinDescriptor builtin = builtinProfile.profile(function.getRBuiltin()); RArgsValuesAndNames argAndNames = (RArgsValuesAndNames) explicitArgs.execute(frame); - RStringVector type = argAndNames.isEmpty() ? null : classHierarchyNode.execute(promiseHelperNode.checkEvaluate(frame, argAndNames.getArgument(0))); + Object dispatchObject = argAndNames.getArgument(0); + + if (isAttributableProfile.profile(dispatchObject instanceof RAttributeStorage) && isS4Profile.profile(((RAttributeStorage) dispatchObject).isS4())) { + RList list = (RList) promiseHelperNode.checkEvaluate(frame, REnvironment.getRegisteredNamespace("methods").get(".BasicFunsList")); + // TODO create a node that looksup the name in the names attribute + int index = list.getElementIndexByName(builtin.getName()); + if (index != -1) { + RFunction basicFun = (RFunction) list.getDataAt(index); + Object result = call.execute(frame, basicFun, argAndNames, null, null); + if (result != RRuntime.DEFERRED_DEFAULT_MARKER) { + return result; + } + } + } + + RStringVector type = argAndNames.isEmpty() ? null : classHierarchyNode.execute(promiseHelperNode.checkEvaluate(frame, dispatchObject)); S3Args s3Args; RFunction resultFunction; if (implicitTypeProfile.profile(type != null)) { @@ -379,6 +411,8 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS @Cached("createBinaryProfile()") ConditionProfile resultIsBuiltinProfile, @Cached("createBinaryProfile()") ConditionProfile summaryGroupNaRmProfile, @Cached("createBinaryProfile()") ConditionProfile summaryGroupProfile, + @Cached("createBinaryProfile()") ConditionProfile isAttributableProfile, + @Cached("createBinaryProfile()") ConditionProfile isS4Profile, @Cached("createPromiseHelper()") PromiseCheckHelperNode promiseHelperNode, @Cached("createUninitializedExplicitCall()") FunctionDispatch call, @Cached("create()") GetBaseEnvFrameNode getBaseEnvFrameNode) { @@ -398,7 +432,20 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS typeXIdx = 1; } - RStringVector typeX = classHierarchyNodeX.execute(promiseHelperNode.checkEvaluate(frame, args[typeXIdx])); + Object dispatchObject = promiseHelperNode.checkEvaluate(frame, args[typeXIdx]); + + if (isAttributableProfile.profile(dispatchObject instanceof RAttributeStorage) && isS4Profile.profile(((RAttributeStorage) dispatchObject).isS4())) { + RList list = (RList) promiseHelperNode.checkEvaluate(frame, REnvironment.getRegisteredNamespace("methods").get(".BasicFunsList")); + int index = list.getElementIndexByName(builtin.getName()); + if (index != -1) { + RFunction basicFun = (RFunction) list.getDataAt(index); + Object result = call.execute(frame, basicFun, new RArgsValuesAndNames(args, argsSignature), null, null); + if (result != RRuntime.DEFERRED_DEFAULT_MARKER) { + return result; + } + } + } + RStringVector typeX = classHierarchyNodeX.execute(dispatchObject); Result resultX = null; if (implicitTypeProfileX.profile(typeX != null)) { resultX = dispatchLookupX.execute(frame, builtin.getName(), typeX, dispatch.getGroupGenericName(), frame.materialize(), getBaseEnvFrameNode.execute()); @@ -483,10 +530,9 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS @Child private CallArgumentsNode arguments; @Child private Node foreignCall; + @Child private Node isNullCall; @CompilationFinal private int foreignCallArgCount; - private final BranchProfile errorProfile = BranchProfile.create(); - public ForeignCall(CallArgumentsNode arguments) { this.arguments = arguments; } @@ -499,15 +545,20 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS foreignCallArgCount = argumentsArray.length; } try { - Object result = ForeignAccess.sendExecute(foreignCall, function, argumentsArray); - if (result instanceof Boolean) { - // convert to R logical - // TODO byte/short convert to int? - result = RRuntime.asLogical((boolean) result); + Object result = ForeignAccess.sendExecute(foreignCall, function, RRuntime.r2Java(argumentsArray)); + if (RRuntime.isForeignObject(result)) { + if (isNullCall == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + isNullCall = insert(Message.IS_NULL.createNode()); + } + if (ForeignAccess.sendIsNull(isNullCall, (TruffleObject) result)) { + return RNull.instance; + } } - return result; - } catch (Throwable e) { - errorProfile.enter(); + return RRuntime.java2R(result); + } catch (ArityException | UnsupportedMessageException | UnsupportedTypeException e) { + CompilerDirectives.transferToInterpreter(); + RInternalError.reportError(e); throw RError.interopError(RError.findParentRBase(this), e, function); } } @@ -599,14 +650,13 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS @Override public Object execute(VirtualFrame frame) { try { - return frame.getObject(slot); + return FrameSlotChangeMonitor.getObject(slot, frame); } catch (FrameSlotTypeException e) { throw RInternalError.shouldNotReachHere(); } } } - @TypeSystemReference(EmptyTypeSystemFlatLayout.class) public abstract static class FunctionDispatch extends Node { /** @@ -737,7 +787,6 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS @Child private RBuiltinNode builtin; @Child private PromiseCheckHelperNode varArgsPromiseHelper; @Children private final PromiseHelperNode[] promiseHelpers; - @Children private final CastNode[] casts; @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); // not using profiles to save overhead @@ -755,7 +804,6 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS this.builtin = builtin; this.builtinDescriptor = builtinDescriptor; this.explicitArgs = explicitArgs; - this.casts = builtin.getCasts(); this.formals = formalArguments; promiseHelpers = new PromiseHelperNode[formals.getLength()]; argEmptySeen = new boolean[formals.getLength()]; @@ -764,6 +812,19 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS wrapSeen = new boolean[formals.getLength()]; } + @Override + protected RBaseNode getErrorContext() { + return builtin.getErrorContext(); + } + + public RBuiltinNode getBuiltin() { + return builtin; + } + + public FormalArguments getFormals() { + return formals; + } + @ExplodeLoop public Object[] castArguments(VirtualFrame frame, Object[] args) { int argCount = formals.getLength(); @@ -798,12 +859,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS } arg = promiseHelpers[i].evaluate(frame, (RPromise) arg); } - if (i < casts.length && casts[i] != null) { - assert builtinDescriptor.evaluatesArg(i); - arg = casts[i].execute(arg); - } } else { - assert casts.length <= i || casts[i] == null : "no casts allowed on non-evaluated arguments in builtin " + builtinDescriptor.getName(); if (arg instanceof RPromise || arg instanceof RMissing) { if (!nonWrapSeen[i]) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -871,7 +927,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS @Override public Object execute(VirtualFrame frame, RFunction currentFunction, RArgsValuesAndNames orderedArguments, S3Args s3Args) { - Object result = builtin.executeBuiltin(frame, castArguments(frame, orderedArguments.getArguments())); + Object result = builtin.call(frame, castArguments(frame, orderedArguments.getArguments())); assert result != null : "builtins cannot return 'null': " + builtinDescriptor.getName(); assert !(result instanceof RConnection) : "builtins cannot return connection': " + builtinDescriptor.getName(); visibility.execute(frame, builtinDescriptor.getVisibility()); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java index 51c882d0911cd9b666a037cb5c548f6145dfe1f8..eec4759c7483a6ecb073fa41f1a5acf07024c4a2 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java @@ -24,7 +24,11 @@ package com.oracle.truffle.r.nodes.function; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.NodeCost; +import com.oracle.truffle.api.nodes.NodeInfo; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.api.source.SourceSection; @@ -36,11 +40,13 @@ import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.RDispatch; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RVisibility; +import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor; import com.oracle.truffle.r.runtime.builtins.RSpecialFactory; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RPromise; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant; @@ -55,8 +61,10 @@ final class PeekLocalVariableNode extends RNode implements RSyntaxLookup { private final ConditionProfile isPromiseProfile = ConditionProfile.createBinaryProfile(); private final ValueProfile valueProfile = ValueProfile.createClassProfile(); + @Child private SetVisibilityNode visibility; + PeekLocalVariableNode(String name) { - this.read = LocalReadVariableNode.create(name, false); + this.read = LocalReadVariableNode.create(Utils.intern(name), false); } @Override @@ -75,6 +83,19 @@ final class PeekLocalVariableNode extends RNode implements RSyntaxLookup { return valueProfile.profile(value); } + @Override + public Object visibleExecute(VirtualFrame frame) { + try { + return execute(frame); + } finally { + if (visibility == null) { + CompilerDirectives.transferToInterpreter(); + visibility = insert(SetVisibilityNode.create()); + } + visibility.execute(frame, true); + } + } + @Override public void setSourceSection(SourceSection source) { // nothing to do @@ -96,6 +117,7 @@ final class PeekLocalVariableNode extends RNode implements RSyntaxLookup { } } +@NodeInfo(cost = NodeCost.NONE) public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode, RSyntaxCall { private static final boolean useSpecials = FastROptions.UseSpecials.getBooleanValue(); @@ -120,6 +142,11 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode return sourceSection; } + @Override + protected RBaseNode getErrorContext() { + return this; + } + @Child private RNode functionNode; @Child private RNode special; @Child private SetVisibilityNode visibility; @@ -140,7 +167,11 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode */ private RCallSpecialNode callSpecialParent; - private RCallSpecialNode(SourceSection sourceSection, RNode functionNode, RFunction expectedFunction, RSyntaxNode[] arguments, ArgumentsSignature signature, RNode special) { + private final boolean inReplace; + private final int[] ignoredArguments; + + private RCallSpecialNode(SourceSection sourceSection, RNode functionNode, RFunction expectedFunction, RSyntaxNode[] arguments, ArgumentsSignature signature, RNode special, boolean inReplace, + int[] ignoredArguments) { this.sourceSection = sourceSection; this.expectedFunction = expectedFunction; this.special = special; @@ -148,6 +179,8 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode this.arguments = arguments; this.signature = signature; this.visible = expectedFunction.getRBuiltin().getVisibility(); + this.inReplace = inReplace; + this.ignoredArguments = ignoredArguments; } /** @@ -216,6 +249,9 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode return null; } if (i < evaluatedArgs) { + // not quite correct: + // || (dispatch == RDispatch.DEFAULT + // && builtinDescriptor.evaluatesArg(i)) localArguments[i] = arg.asRNode(); } else { localArguments[i] = new PeekLocalVariableNode(lookup); @@ -236,7 +272,7 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode RFunction expectedFunction = RContext.lookupBuiltin(name); RInternalError.guarantee(expectedFunction != null); - RCallSpecialNode callSpecial = new RCallSpecialNode(sourceSection, functionNode, expectedFunction, arguments, signature, special); + RCallSpecialNode callSpecial = new RCallSpecialNode(sourceSection, functionNode, expectedFunction, arguments, signature, special, inReplace, ignoredArguments); for (int i = 0; i < arguments.length; i++) { if (!inReplace || !contains(ignoredArguments, i)) { if (arguments[i] instanceof RCallSpecialNode) { @@ -288,6 +324,23 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode } } + @TruffleBoundary + private static void log(String format, Object... args) { + System.out.println(String.format(format, args)); + } + + @Override + public Node deepCopy() { + assert !inReplace && callSpecialParent == null && ignoredArguments.length == 0; + RCallSpecialNode node = (RCallSpecialNode) RContext.getASTBuilder().process(this).asRNode(); + node.functionNode = node.insert(node.functionNode); + node.special = node.insert(node.special); + if (node.visibility != null) { + node.visibility = insert(node.visibility); + } + return node; + } + private RCallNode getRCallNode(RSyntaxNode[] newArguments) { return RCallNode.createCall(sourceSection, functionNode, signature, newArguments); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java index 2e26f58248200f61c0a9b8aaac51c7b5a925dff7..065db4b08840904abb2649c1178a72998df720cb 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.function; +import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameSlot; @@ -31,7 +32,8 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.REmpty; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RPromise; -import com.oracle.truffle.r.runtime.data.RPromise.EagerPromiseBase; +import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; /** * This class implements the behavior for {@link RMissing} which is needed inside this module, as it @@ -83,6 +85,7 @@ public class RMissingHelper { * type is not object. */ public static Object getMissingValue(Frame frame, String name) { + CompilerAsserts.neverPartOfCompilation(); // Check binding FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(name); if (frameSlot == null) { @@ -91,7 +94,7 @@ public class RMissingHelper { // Read name's value try { - return frame.getObject(frameSlot); + return FrameSlotChangeMonitor.getObject(frameSlot, frame); } catch (FrameSlotTypeException e) { return null; } @@ -135,8 +138,8 @@ public class RMissingHelper { } promise.setUnderEvaluation(); // TODO Profile necessary here??? - if (promise instanceof EagerPromiseBase) { - EagerPromiseBase eagerPromise = (EagerPromiseBase) promise; + if (promise instanceof EagerPromise) { + EagerPromise eagerPromise = (EagerPromise) promise; if (!eagerPromise.isDeoptimized()) { Object eagerValue = eagerPromise.getEagerValue(); if (eagerValue instanceof RPromise) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java index bbce4bf49e0fc2c3d86a9cc6fc882f2d635a9e4e..e7921cf9d346bc1fe281a94b8b7c96ec6d2e4837 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java @@ -45,6 +45,7 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.RBaseNode; public abstract class S3FunctionLookupNode extends RBaseNode { @@ -437,7 +438,7 @@ public abstract class S3FunctionLookupNode extends RBaseNode { return null; } try { - return genericDefFrame.getObject(slot); + return FrameSlotChangeMonitor.getObject(slot, genericDefFrame); } catch (FrameSlotTypeException e) { throw RInternalError.shouldNotReachHere(); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/TemporarySlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/TemporarySlotNode.java index 03e13b0d068b6a277a8511029d130b4bab6ba20b..1d7589976a4b39ca52e90a91ab45547ccd373d79 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/TemporarySlotNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/TemporarySlotNode.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 @@ -30,10 +30,12 @@ import com.oracle.truffle.api.frame.FrameSlotTypeException; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; +import com.oracle.truffle.r.runtime.env.frame.RFrameSlot; public final class TemporarySlotNode extends Node { - private static final Object[] defaultTempIdentifiers = new Object[]{new Object(), new Object(), new Object(), new Object(), new Object(), new Object(), new Object(), new Object()}; + private static final RFrameSlot[] defaultTempIdentifiers = new RFrameSlot[]{RFrameSlot.createTemp(true), RFrameSlot.createTemp(true), RFrameSlot.createTemp(true), RFrameSlot.createTemp(true)}; @CompilationFinal private FrameSlot tempSlot; private int tempIdentifier; @@ -41,7 +43,7 @@ public final class TemporarySlotNode extends Node { public FrameSlot initialize(VirtualFrame frame, Object value) { if (tempSlot == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - tempSlot = frame.getFrameDescriptor().findOrAddFrameSlot(defaultTempIdentifiers[0], FrameSlotKind.Object); + tempSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), defaultTempIdentifiers[0], FrameSlotKind.Object); } FrameSlot slot = tempSlot; try { @@ -50,8 +52,8 @@ public final class TemporarySlotNode extends Node { // keep the complete loop in the slow path do { tempIdentifier++; - Object identifier = tempIdentifier < defaultTempIdentifiers.length ? defaultTempIdentifiers[tempIdentifier] : new Object(); - tempSlot = slot = frame.getFrameDescriptor().findOrAddFrameSlot(identifier, FrameSlotKind.Object); + RFrameSlot identifier = tempIdentifier < defaultTempIdentifiers.length ? defaultTempIdentifiers[tempIdentifier] : RFrameSlot.createTemp(true); + tempSlot = slot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), identifier, FrameSlotKind.Object); if (frame.getObject(slot) == null) { break; } @@ -61,16 +63,16 @@ public final class TemporarySlotNode extends Node { CompilerDirectives.transferToInterpreter(); throw RInternalError.shouldNotReachHere(); } - frame.setObject(slot, value); + FrameSlotChangeMonitor.setObject(frame, slot, value); return slot; } public static void cleanup(VirtualFrame frame, Object object, FrameSlot tempSlot) { try { - assert frame.getObject(tempSlot) == object; + assert FrameSlotChangeMonitor.getObject(tempSlot, frame) == object; } catch (FrameSlotTypeException e) { throw RInternalError.shouldNotReachHere(); } - frame.setObject(tempSlot, null); + FrameSlotChangeMonitor.setObject(frame, tempSlot, null); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentBaseNode.java index ebc6853f82b99c2b42960331e645ed0d5de65090..a86dd95a42ace8bde644958eb8ce6ae1289d1681 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentBaseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentBaseNode.java @@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.function; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @@ -65,10 +64,10 @@ public abstract class WrapArgumentBaseNode extends RNode { } public Object execute(VirtualFrame frame, Object result) { + RSharingAttributeStorage.verify(result); if (isShareable.profile(result instanceof RSharingAttributeStorage)) { return handleShareable(frame, (RSharingAttributeStorage) result); } else { - assert !(result instanceof RShareable) : "unexpected RShareable that is not a subclass of RSharingAttributeStorage"; return result; } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.java index 64f43e7ee5b33582a857a9a57cee82ddcf69a0dc..5d1a666e1b09234ab4b736648645e122f10ad6cf 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.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 @@ -26,8 +26,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.UnexpectedResultException; import com.oracle.truffle.r.nodes.access.ConstantNode; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage; import com.oracle.truffle.r.runtime.nodes.RNode; @@ -88,24 +86,6 @@ public final class WrapArgumentNode extends WrapArgumentBaseNode { } } - @Override - public RMissing executeMissing(VirtualFrame frame) throws UnexpectedResultException { - try { - return operand.executeMissing(frame); - } catch (UnexpectedResultException e) { - throw new UnexpectedResultException(execute(frame, e.getResult())); - } - } - - @Override - public RNull executeNull(VirtualFrame frame) throws UnexpectedResultException { - try { - return operand.executeNull(frame); - } catch (UnexpectedResultException e) { - throw new UnexpectedResultException(execute(frame, e.getResult())); - } - } - static WrapArgumentNode create(int index) { return new WrapArgumentNode(null, index); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareArguments.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareArguments.java index d19da1dc99641c190803d58b675f2abdc8a19b64..554d2b2b0e16ba18889f4639f3bedf04492ec9e5 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareArguments.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareArguments.java @@ -27,11 +27,9 @@ 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.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.nodes.RRootNode; import com.oracle.truffle.r.nodes.function.ArgumentMatcher; import com.oracle.truffle.r.nodes.function.ArgumentMatcher.MatchPermutation; @@ -53,7 +51,6 @@ import com.oracle.truffle.r.runtime.nodes.RNode; * rules. It implements two different paths: one for arguments provided as an * {@link CallArgumentsNode}, i.e., unevaluated arguments, and another path for evaluated arguments. */ -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) public abstract class PrepareArguments extends Node { protected static final int CACHE_SIZE = 8; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareMatchInternalArguments.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareMatchInternalArguments.java new file mode 100644 index 0000000000000000000000000000000000000000..23b150ba129ea609c0df36c851469658e5b813ef --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareMatchInternalArguments.java @@ -0,0 +1,81 @@ +/* + * 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.nodes.function.call; + +import java.util.Objects; + +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.nodes.Node; +import com.oracle.truffle.r.nodes.function.ArgumentMatcher; +import com.oracle.truffle.r.nodes.function.ArgumentMatcher.MatchPermutation; +import com.oracle.truffle.r.nodes.function.FormalArguments; +import com.oracle.truffle.r.nodes.function.RCallNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RArguments.S3DefaultArguments; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; + +/** + * Basically the same as {@link PrepareArguments} but for a specific set of internal generic + * functions using a vararg parameter but expecting a specific amount of parameters by internally + * matching them. + */ +public abstract class PrepareMatchInternalArguments extends Node { + + protected static final int CACHE_SIZE = 8; + + protected final RBaseNode callingNode; + protected final FormalArguments formals; + + protected PrepareMatchInternalArguments(FormalArguments formals, RBaseNode callingNode) { + this.callingNode = Objects.requireNonNull(callingNode); + this.formals = Objects.requireNonNull(formals); + } + + protected MatchPermutation createArguments(ArgumentsSignature supplied) { + return ArgumentMatcher.matchArguments(supplied, formals.getSignature(), callingNode, null); + } + + @Specialization(limit = "CACHE_SIZE", guards = {"cachedExplicitArgSignature == explicitArgs.getSignature()"}) + public RArgsValuesAndNames prepare(RArgsValuesAndNames explicitArgs, S3DefaultArguments s3DefaultArguments, + @SuppressWarnings("unused") @Cached("explicitArgs.getSignature()") ArgumentsSignature cachedExplicitArgSignature, + @Cached("createArguments(cachedExplicitArgSignature)") MatchPermutation permutation) { + return ArgumentMatcher.matchArgumentsEvaluated(permutation, explicitArgs.getArguments(), s3DefaultArguments, formals); + } + + @Fallback + @TruffleBoundary + public RArgsValuesAndNames prepareGeneric(RArgsValuesAndNames evaluatedArgs, S3DefaultArguments s3DefaultArguments) { + return ArgumentMatcher.matchArgumentsEvaluated(formals, evaluatedArgs, s3DefaultArguments, callingNode); + } + + /** + * Returns the argument values and corresponding signature. The signature represents the + * original call signature reordered in the same way as the arguments. For s3DefaultArguments + * motivation see {@link RCallNode#callGroupGeneric}. + */ + public abstract RArgsValuesAndNames execute(RArgsValuesAndNames evaluatedArgs, S3DefaultArguments s3DefaultArguments); +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/RExplicitCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/RExplicitCallNode.java index 7f6354db2fe120fa7eb56e0ebabe4607b0d7475f..b856c58620a7b6e111ee35ca431ca0c57779f4a5 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/RExplicitCallNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/RExplicitCallNode.java @@ -22,50 +22,52 @@ */ package com.oracle.truffle.r.nodes.function.call; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.FrameSlot; +import com.oracle.truffle.api.frame.FrameSlotKind; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.r.nodes.access.FrameSlotNode; import com.oracle.truffle.r.nodes.function.RCallBaseNode; import com.oracle.truffle.r.nodes.function.RCallNode; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; +import com.oracle.truffle.r.runtime.env.frame.RFrameSlot; /** * Helper node that allows to call a given function with explicit arguments. */ public abstract class RExplicitCallNode extends Node { + public static RExplicitCallNode create() { return RExplicitCallNodeGen.create(); } public abstract Object execute(VirtualFrame frame, RFunction function, RArgsValuesAndNames args); + private final RFrameSlot argsIdentifier = RFrameSlot.createTemp(true); + @CompilationFinal private FrameSlot argsFrameSlot; + @Specialization - Object doCall(VirtualFrame frame, RFunction function, RArgsValuesAndNames args, - @SuppressWarnings("unused") @Cached("createArgsIdentifier()") Object argsIdentifier, - @Cached("createExplicitCall(argsIdentifier)") RCallBaseNode call, - @Cached("createFrameSlotNode(argsIdentifier)") FrameSlotNode argumentsSlot) { - FrameSlot argsFrameSlot = argumentsSlot.executeFrameSlot(frame); + protected Object doCall(VirtualFrame frame, RFunction function, RArgsValuesAndNames args, + @Cached("createExplicitCall()") RCallBaseNode call) { + if (argsFrameSlot == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + argsFrameSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), argsIdentifier, FrameSlotKind.Object); + } try { frame.setObject(argsFrameSlot, args); + FrameSlotChangeMonitor.setObject(frame, argsFrameSlot, args); return call.execute(frame, function); } finally { - frame.setObject(argsFrameSlot, null); + FrameSlotChangeMonitor.setObject(frame, argsFrameSlot, null); } } - static Object createArgsIdentifier() { - return new Object(); - } - - static RCallBaseNode createExplicitCall(Object argsIdentifier) { + protected RCallBaseNode createExplicitCall() { return RCallNode.createExplicitCall(argsIdentifier); } - - static FrameSlotNode createFrameSlotNode(Object argsIdentifier) { - return FrameSlotNode.createTemp(argsIdentifier, true); - } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptForcedEagerPromiseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptForcedEagerPromiseNode.java index 5ffc0cef62163e1339a4c7a4fc316cc5fc02ca1b..73380b076b96549b3ddacea79e07178ea0573705 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptForcedEagerPromiseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptForcedEagerPromiseNode.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 @@ -27,6 +27,7 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.function.ArgumentStatePush; import com.oracle.truffle.r.nodes.function.PromiseHelperNode; import com.oracle.truffle.r.nodes.function.PromiseNode; @@ -46,8 +47,9 @@ public final class OptForcedEagerPromiseNode extends PromiseNode { @Child private RNode expr; @Child private PromiseHelperNode promiseHelper; + private final ConditionProfile firstPromise = ConditionProfile.createBinaryProfile(); + private final ConditionProfile promiseCallerProfile = ConditionProfile.createBinaryProfile(); private final BranchProfile nonPromiseProfile = BranchProfile.create(); - private final BranchProfile promiseCallerProfile = BranchProfile.create(); private final RPromiseFactory factory; private final int wrapIndex; @@ -83,9 +85,11 @@ public final class OptForcedEagerPromiseNode extends PromiseNode { nonPromiseProfile.enter(); } RCaller call = RArguments.getCall(frame); - while (call.isPromise()) { - promiseCallerProfile.enter(); + if (firstPromise.profile(call.isPromise())) { call = call.getParent(); + while (promiseCallerProfile.profile(call.isPromise())) { + call = call.getParent(); + } } return factory.createEagerSuppliedPromise(value, alwaysValidAssumption, call, null, wrapIndex); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ReuseNonSharedNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ReuseNonSharedNode.java index b5d62266067b674b99932bf142ce193d5c835727..09ef7a3fc56c1c0f0474bb0b4947012ffbb12f00 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ReuseNonSharedNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ReuseNonSharedNode.java @@ -22,56 +22,74 @@ */ package com.oracle.truffle.r.nodes.function.opt; +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.nodes.Node; import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage; +import com.oracle.truffle.r.runtime.data.RVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; /** * Internal node that should be used whenever you want to alter some data: if the data is shared, * then it creates a copy, otherwise it returns the data. It does not increment the reference count * of the result in either case, but that is typically handled by write variable node, put container * element node or by put attribute node. + * + * This node also makes sure that the returned value is an actual RVector in which individual + * elements can be modified (as opposed to sequences, etc.) by calling materialize. */ public abstract class ReuseNonSharedNode extends Node { + protected static final int LIMIT = 5; + public static ReuseNonSharedNode create() { return ReuseNonSharedNodeGen.create(); } - public abstract Object execute(Object value); + public abstract RVector<?> execute(RAbstractVector value); - @Specialization - protected RShareable getStorage(RSharingAttributeStorage value, - @Cached("createBinaryProfile()") ConditionProfile isSharedProfile, - @Cached("createClassProfile()") ValueProfile copyProfile) { - if (isSharedProfile.profile(value.isShared())) { - RShareable res = copyProfile.profile(value).copy(); + @Specialization(limit = "LIMIT", guards = "value.getClass() == valueClass") + protected RVector<?> reuseNonShareable(RAbstractVector value, + @Cached("value.getClass()") Class<? extends RAbstractVector> valueClass, + @Cached("createBinaryProfile()") ConditionProfile isSharedProfile) { + RAbstractVector profiledValue = valueClass.cast(value); + if (RShareable.class.isAssignableFrom(valueClass)) { + RShareable shareable = (RShareable) profiledValue; + if (isSharedProfile.profile(shareable.isShared())) { + RShareable res = shareable.copy(); + assert res.isTemporary(); + return (RVector<?>) res; + } else { + return (RVector<?>) profiledValue; + } + } else { + RVector<?> res = profiledValue.materialize(); assert res.isTemporary(); return res; } - return value; } - @Specialization(replaces = "getStorage") - protected static RShareable getRShareable(RShareable value, - @Cached("createBinaryProfile()") ConditionProfile isSharedProfile) { - if (isSharedProfile.profile(value.isShared())) { - RShareable res = value.copy(); + @Fallback + @TruffleBoundary + public static RVector<?> reuseSlow(RAbstractVector value) { + RSharingAttributeStorage.verify(value); + if (value instanceof RSharingAttributeStorage) { + RShareable shareable = (RShareable) value; + if (shareable.isShared()) { + RShareable res = shareable.copy(); + assert res.isTemporary(); + return (RVector<?>) res; + } else { + return (RVector<?>) value; + } + } else { + RVector<?> res = value.materialize(); + assert res.isTemporary(); return res; } - return value; - } - - protected static boolean isRShareable(Object value) { - return value instanceof RShareable; - } - - @Specialization(guards = "!isRShareable(value)") - protected static Object getNonShareable(Object value) { - return value; } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ShareObjectNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ShareObjectNode.java index 523d27ac3dad13c7f740eb9888494b25c39c772a..2d99d451174b1ae5c0fa3219f236b36dff91122c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ShareObjectNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ShareObjectNode.java @@ -25,12 +25,11 @@ package com.oracle.truffle.r.nodes.function.opt; import static com.oracle.truffle.api.nodes.NodeCost.NONE; 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.dsl.TypeSystemReference; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeInfo; import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage; @@ -42,9 +41,9 @@ import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage; * This class relies (and asserts) that all RShareable objects are subclasses of * RSharingAttributeStorage. */ -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) @NodeInfo(cost = NONE) public abstract class ShareObjectNode extends Node { + public abstract Object execute(Object obj); public static ShareObjectNode create() { @@ -60,18 +59,14 @@ public abstract class ShareObjectNode extends Node { return obj; } - @Specialization(guards = "!isRShareable(obj)") + @Fallback protected Object doNonShareable(Object obj) { + RSharingAttributeStorage.verify(obj); return obj; } - protected static boolean isRShareable(Object value) { - verify(value); - return value instanceof RSharingAttributeStorage; - } - public static <T> T share(T value) { - verify(value); + RSharingAttributeStorage.verify(value); if (value instanceof RSharingAttributeStorage) { RSharingAttributeStorage shareable = (RSharingAttributeStorage) value; if (!shareable.isSharedPermanent()) { @@ -82,7 +77,7 @@ public abstract class ShareObjectNode extends Node { } public static <T> T sharePermanent(T value) { - verify(value); + RSharingAttributeStorage.verify(value); if (value instanceof RSharingAttributeStorage) { ((RSharingAttributeStorage) value).makeSharedPermanent(); } @@ -90,7 +85,7 @@ public abstract class ShareObjectNode extends Node { } public static void unshare(Object value) { - verify(value); + RSharingAttributeStorage.verify(value); if (value instanceof RSharingAttributeStorage) { RSharingAttributeStorage shareable = (RSharingAttributeStorage) value; if (!shareable.isSharedPermanent()) { @@ -98,8 +93,4 @@ public abstract class ShareObjectNode extends Node { } } } - - private static void verify(Object value) { - assert (value instanceof RShareable) == (value instanceof RSharingAttributeStorage) : "unexpected RShareable that is not RSharingAttributeStorage: " + value; - } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/UpdateShareableChildValueNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/UpdateShareableChildValueNode.java index 7787564d54026369851f40c0c19a5d2b13548305..fb71c60e5ea88f609c93cbbde820c487e3d28a60 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/UpdateShareableChildValueNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/UpdateShareableChildValueNode.java @@ -23,18 +23,14 @@ package com.oracle.truffle.r.nodes.function.opt; 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.profiles.ConditionProfile; -import com.oracle.truffle.api.profiles.ValueProfile; -import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage; import com.oracle.truffle.r.runtime.nodes.RBaseNode; public abstract class UpdateShareableChildValueNode extends RBaseNode { - protected UpdateShareableChildValueNode() { - } - public abstract void execute(Object owner, Object attrValue); public final <T> T updateState(Object owner, T item) { @@ -47,30 +43,13 @@ public abstract class UpdateShareableChildValueNode extends RBaseNode { } @Specialization - protected void doShareableValues(RShareable owner, RShareable value, - @Cached("createClassProfile()") ValueProfile valueProfile, - @Cached("createBinaryProfile()") ConditionProfile sharingAttrsStorageOwner, - @Cached("createClassProfile()") ValueProfile ownerProfile, + protected void doShareableValues(RSharingAttributeStorage owner, RSharingAttributeStorage value, @Cached("createBinaryProfile()") ConditionProfile sharedValue, @Cached("createBinaryProfile()") ConditionProfile temporaryOwner) { - RShareable profiledValue = valueProfile.profile(value); - if (sharedValue.profile(profiledValue.isShared())) { + if (sharedValue.profile(value.isShared())) { // it is already shared, not need to do anything return; } - - if (sharingAttrsStorageOwner.profile(owner instanceof RSharingAttributeStorage)) { - // monomorphic invocations of the owner - RSharingAttributeStorage shOwner = (RSharingAttributeStorage) owner; - incRef(shOwner, profiledValue, temporaryOwner); - } else { - // invoking a type-profiled owner - RShareable ownerProfiled = ownerProfile.profile(owner); - incRef(ownerProfiled, profiledValue, temporaryOwner); - } - } - - private static void incRef(RShareable owner, RShareable value, ConditionProfile temporaryOwner) { if (temporaryOwner.profile(owner.isTemporary())) { // This can happen, for example, when we immediately extract out of a temporary // list that was returned by a built-in, like: strsplit(...)[[1L]]. We do not need @@ -79,7 +58,6 @@ public abstract class UpdateShareableChildValueNode extends RBaseNode { } // the owner is at least non-shared - if (value.isTemporary()) { // make it at least non-shared (the owner must be also at least non-shared) value.incRefCount(); @@ -90,12 +68,9 @@ public abstract class UpdateShareableChildValueNode extends RBaseNode { } } - @Specialization(guards = "isFallback(owner, value)") - @SuppressWarnings("unused") + @Fallback protected void doFallback(Object owner, Object value) { - } - - protected static boolean isFallback(Object owner, Object value) { - return !(value instanceof RShareable) || !(owner instanceof RShareable); + RSharingAttributeStorage.verify(owner); + RSharingAttributeStorage.verify(value); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CollectArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CollectArgumentsNode.java index 0be21e8e3d00446e09e77aa542f44d923380e5a2..9b7f4252103eae8aecd36871d8aa1461121922be 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CollectArgumentsNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CollectArgumentsNode.java @@ -38,6 +38,7 @@ import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RPromise; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.RBaseNode; public abstract class CollectArgumentsNode extends RBaseNode { @@ -88,7 +89,7 @@ public abstract class CollectArgumentsNode extends RBaseNode { if (slot == null) { result[i] = RMissing.instance; } else { - result[i] = frame.getValue(slot); + result[i] = FrameSlotChangeMonitor.getValue(slot, frame); } } return result; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CombineSignaturesNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CombineSignaturesNode.java index 35e5972874d5c1619d1237938ffc2f489560f5d4..89f8b2a4e8c898d0b85ca66ee9d8ad0019848854 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CombineSignaturesNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CombineSignaturesNode.java @@ -27,9 +27,7 @@ import java.util.Arrays; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.nodes.RBaseNode; @@ -45,7 +43,6 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; * * @see com.oracle.truffle.r.nodes.function.ArgumentMatcher */ -@TypeSystemReference(EmptyTypeSystemFlatLayout.class) public abstract class CombineSignaturesNode extends RBaseNode { protected static final int CACHE_LIMIT = 3; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java index 1ac6ee892212d1d89aa7d594271e67a34642e026..98aff46476a515d2deaa16bbf3bb93892e17639f 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java @@ -40,13 +40,14 @@ import com.oracle.truffle.r.nodes.function.RMissingHelper; import com.oracle.truffle.r.nodes.function.signature.MissingNodeFactory.MissingCheckCacheNodeGen; import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; -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.RRuntime; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise; +import com.oracle.truffle.r.runtime.data.RPromise.PromiseState; +import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant; import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; @@ -142,7 +143,7 @@ public final class MissingNode extends OperatorNode { if (isSymbolNullProfile.profile(symbol == null)) { return false; } else { - if (promise instanceof EagerPromise && !((EagerPromise) promise).isDeoptimized()) { + if (PromiseState.isEager(promise.getState()) && !((EagerPromise) promise).isDeoptimized()) { return false; } if (recursiveDesc != null) { @@ -199,13 +200,17 @@ public final class MissingNode extends OperatorNode { if (level == null && readVarArgs == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); if (args.length != 1) { - throw RError.error(this, Message.ARGUMENTS_PASSED, args.length, "'missing'", 1); + throw error(Message.ARGUMENTS_PASSED, args.length, "'missing'", 1); } RSyntaxElement arg = args[0]; - if (!(arg instanceof RSyntaxLookup)) { - throw RError.error(this, Message.INVALID_USE, "missing"); + String identifier; + if (arg instanceof RSyntaxConstant && ((RSyntaxConstant) arg).getValue() instanceof String) { + identifier = (String) ((RSyntaxConstant) arg).getValue(); + } else if (arg instanceof RSyntaxLookup) { + identifier = ((RSyntaxLookup) arg).getIdentifier(); + } else { + throw error(Message.INVALID_USE, "missing"); } - String identifier = ((RSyntaxLookup) arg).getIdentifier(); if (ArgumentsSignature.VARARG_NAME.equals(identifier)) { readVarArgs = insert(LocalReadVariableNode.create(ArgumentsSignature.VARARG_NAME, false)); } else { @@ -219,7 +224,7 @@ public final class MissingNode extends OperatorNode { RArgsValuesAndNames varArgs = (RArgsValuesAndNames) readVarArgs.execute(frame); if (varArgs == null) { CompilerDirectives.transferToInterpreter(); - throw RError.error(this, Message.MISSING_ARGUMENTS); + throw error(Message.MISSING_ARGUMENTS); } return createResult(frame, varArgs.getLength() == 0); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/GetVisibilityNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/GetVisibilityNode.java index 61a735b9465ee9af14bdd25090a6f20dcb104ca7..b59180138a7b98913bb93d00fb60b0292b016802 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/GetVisibilityNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/GetVisibilityNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -32,6 +32,7 @@ import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.nodes.NodeInfo; import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.env.frame.RFrameSlot; /** @@ -52,7 +53,7 @@ public final class GetVisibilityNode extends Node { public boolean execute(Frame frame) { if (frameSlot == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - frameSlot = frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.Visibility, FrameSlotKind.Boolean); + frameSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), RFrameSlot.Visibility, FrameSlotKind.Boolean); } try { return frame.getBoolean(frameSlot); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/SetVisibilityNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/SetVisibilityNode.java index a259f498adbd9a3d08e22058bae9dd8d0ecf311c..f3fea2a553b20e487d2da962614b6c4b5738df9d 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/SetVisibilityNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/SetVisibilityNode.java @@ -37,6 +37,7 @@ import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RVisibility; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.env.frame.RFrameSlot; /** @@ -57,7 +58,7 @@ public final class SetVisibilityNode extends Node { private void ensureFrameSlot(Frame frame) { if (frameSlot == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - frameSlot = frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.Visibility, FrameSlotKind.Boolean); + frameSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), RFrameSlot.Visibility, FrameSlotKind.Boolean); } } @@ -103,7 +104,7 @@ public final class SetVisibilityNode extends Node { */ public static void executeAfterCallSlowPath(Frame frame, RCaller caller) { CompilerAsserts.neverPartOfCompilation(); - frame.setBoolean(frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.Visibility, FrameSlotKind.Boolean), caller.getVisibility()); + frame.setBoolean(FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), RFrameSlot.Visibility, FrameSlotKind.Boolean), caller.getVisibility()); } /** @@ -111,6 +112,6 @@ public final class SetVisibilityNode extends Node { */ public static void executeSlowPath(Frame frame, boolean visibility) { CompilerAsserts.neverPartOfCompilation(); - frame.setBoolean(frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.Visibility, FrameSlotKind.Boolean), visibility); + frame.setBoolean(FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), RFrameSlot.Visibility, FrameSlotKind.Boolean), visibility); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/InheritsCheckNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/InheritsCheckNode.java index 16524b3fee37cf67b46dea7acbd8b5783652e15e..9ef1c9bcc6791441d2f7d554b72ffa027a2ce360 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/InheritsCheckNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/InheritsCheckNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -29,6 +29,7 @@ import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen; +import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RStringVector; @@ -49,6 +50,10 @@ public final class InheritsCheckNode extends Node { assert RType.fromMode(checkedClazz) == null : "Class '" + checkedClazz + "' cannot be checked by InheritsCheckNode"; } + public static InheritsCheckNode createFactor() { + return new InheritsCheckNode(RRuntime.CLASS_FACTOR); + } + public boolean execute(Object value) { if (value instanceof RMissing) { return false; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java index 80b354423480cb2b7819a20ccea9f900aabd1361..4f8856e8c6c19f8d3606fe432efc8bb45feb0f7d 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java @@ -77,7 +77,6 @@ public class RInstrumentation { SourceSection fdns = fdn.getSourceSection(); builder.indexIn(fdns.getCharIndex(), fdns.getCharLength()); builder.sourceIs(fdns.getSource()); - builder.rootSourceSectionEquals(fdns); return builder; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.java index 3acb958ef9701fc0229a07e17fafe3d69a94c9f3..f8b51386ac4fa75a5a54bd348c0889c2dae88ed1 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.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 @@ -39,10 +39,13 @@ import com.oracle.truffle.r.nodes.function.PromiseHelperNode; import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.REmpty; import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.RBaseNode; // transcribed from /src/library/methods/src/methods_list_dispatch.c (R_dispatch_generic function) @@ -90,6 +93,9 @@ public abstract class CollectGenericArgumentsNode extends RBaseNode { throw new SlowPathException(); } Object value = argReads[i].execute(frame); + if (value == REmpty.instance || value == RMissing.instance) { + value = null; + } result[i] = valueMissingProfile.profile(value == null) ? "missing" : classHierarchyNodes[i].executeString(promiseHelper.checkEvaluate(frame, value)); } return RDataFactory.createStringVector(result, RDataFactory.COMPLETE_VECTOR); @@ -112,7 +118,7 @@ public abstract class CollectGenericArgumentsNode extends RBaseNode { if (slot == null) { result[i] = "missing"; } else { - Object value = frame.getValue(slot); + Object value = FrameSlotChangeMonitor.getValue(slot, frame); if (value instanceof RPromise) { value = PromiseHelperNode.evaluateSlowPath(null, (RPromise) value); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java index 4619df7873767cf57eb2f9b2b0a24c3512e4f14e..c7403d171a61c224ed320599ac40e8a8cbe4b18b 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java @@ -6,7 +6,7 @@ * Copyright (c) 1995, 1996, 1997 Robert Gentleman and Ross Ihaka * Copyright (c) 1995-2014, The R Core Team * Copyright (c) 2002-2008, The R Foundation - * Copyright (c) 2015, 2016, Oracle and/or its affiliates + * Copyright (c) 2015, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -14,14 +14,12 @@ package com.oracle.truffle.r.nodes.objects; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.r.nodes.RRootNode; import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.function.CallMatcherNode; -import com.oracle.truffle.r.nodes.function.FormalArguments; import com.oracle.truffle.r.nodes.function.signature.CollectArgumentsNode; import com.oracle.truffle.r.nodes.function.signature.CollectArgumentsNodeGen; -import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RArguments.S4Args; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RFunction; @@ -42,15 +40,14 @@ final class ExecuteMethod extends RBaseNode { if (collectArgs == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); collectArgs = insert(CollectArgumentsNodeGen.create()); + } + if (callMatcher == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); callMatcher = insert(CallMatcherNode.create(false)); } - FormalArguments formals = ((RRootNode) fdef.getRootNode()).getFormalArguments(); - ArgumentsSignature signature = formals.getSignature(); - Object[] oldArgs = collectArgs.execute(frame, signature); - S4Args s4Args = new S4Args(readDefined.execute(frame), readMethod.execute(frame), readTarget.execute(frame), readGeneric.execute(frame), readMethods.execute(frame)); - return callMatcher.execute(frame, signature, oldArgs, fdef, fname, s4Args); + return callMatcher.execute(frame, RArguments.getSignature(frame), RArguments.getArguments(frame), fdef, fname, s4Args); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetPrimName.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetPrimName.java index 25920e40449e25802068ac9f1583534586c7af60..8668018df1e2d42ef870e9fba2f4c9054c450e10 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetPrimName.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetPrimName.java @@ -23,12 +23,11 @@ public abstract class GetPrimName extends RExternalBuiltinNode.Arg1 { static { Casts casts = new Casts(GetPrimName.class); - casts.arg(0).defaultError(RError.NO_CALLER, RError.Message.GENERIC, "'R_get_primname' called on a non-primitive").mustBe(builtin()); + casts.arg(0).defaultError(RError.Message.GENERIC, "'R_get_primname' called on a non-primitive").mustBe(builtin()); } @Specialization(guards = "f.isBuiltin()") protected String getPrimName(RFunction f) { return f.getName(); } - } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetS4DataSlot.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetS4DataSlot.java index 8dc96975ebadf202edc586ede634c365eb3475df..6d2ca9ae16f77f59d89a0f82797bd97cd367ec40 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetS4DataSlot.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetS4DataSlot.java @@ -6,7 +6,7 @@ * Copyright (c) 1995, 1996, 1997 Robert Gentleman and Ross Ihaka * Copyright (c) 1995-2014, The R Core Team * Copyright (c) 2002-2008, The R Foundation - * Copyright (c) 2015, 2016, Oracle and/or its affiliates + * Copyright (c) 2015, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -81,14 +81,15 @@ public abstract class GetS4DataSlot extends Node { if (s3Class != null) { if (s3ClassAttrRemove == null) { - assert castToVector == null; CompilerDirectives.transferToInterpreterAndInvalidate(); s3ClassAttrRemove = insert(RemoveFixedAttributeNode.create(RRuntime.DOT_S3_CLASS)); + } + if (castToVector == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); castToVector = insert(CastToVectorNode.create()); - } s3ClassAttrRemove.execute(obj.initAttributes()); - setClassAttrNode.execute(obj, castToVector.execute(s3Class)); + setClassAttrNode.execute(obj, castToVector.doCast(s3Class)); } else { setClassAttrNode.reset(obj); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java index 449eabf4bdbd68285bb9edc49a05224efdbef6b9..236289defb37f1353359c34e785f0b5b943282d6 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java @@ -71,33 +71,38 @@ abstract class LoadMethod extends RBaseNode { @Cached("createClassProfile()") ValueProfile regFrameAccessProfile, @Cached("createClassProfile()") ValueProfile methodsFrameAccessProfile) { DynamicObject attributes = fdef.getAttributes(); - assert attributes != null; // should have at least class attribute + assert fdef.isBuiltin() || attributes != null; int found; - Object nextMethodAttr = nextMethodAttrAccess.execute(attributes); - // it's an optimization only where it's expected that either 2 or 4 attributes total will be - // present - anything else triggers execution of a generic S4 function - if (noNextMethodAttr.profile(nextMethodAttr == null)) { - found = 4; // class attribute plus three others are expected - Object targetAttr = targetAttrAccess.execute(attributes); - if (noTargetAttr.profile(targetAttr == null)) { - found--; + if (attributes != null) { + Object nextMethodAttr = nextMethodAttrAccess.execute(attributes); + // it's an optimization only where it's expected that either 2 or 4 attributes total + // will be + // present - anything else triggers execution of a generic S4 function + if (noNextMethodAttr.profile(nextMethodAttr == null)) { + found = 4; // class attribute plus three others are expected + Object targetAttr = targetAttrAccess.execute(attributes); + if (noTargetAttr.profile(targetAttr == null)) { + found--; + } else { + writeRTarget.execute(frame, targetAttr); + } + Object definedAttr = definedAttrAccess.execute(attributes); + if (noDefinedAttr.profile(definedAttr == null)) { + found--; + } else { + writeRDefined.execute(frame, definedAttr); + } + Object sourceAttr = sourceAttrAccess.execute(attributes); + if (sourceAttr == null) { + noSourceAttr.enter(); + found--; + } } else { - writeRTarget.execute(frame, targetAttr); - } - Object definedAttr = definedAttrAccess.execute(attributes); - if (noDefinedAttr.profile(definedAttr == null)) { - found--; - } else { - writeRDefined.execute(frame, definedAttr); - } - Object sourceAttr = sourceAttrAccess.execute(attributes); - if (sourceAttr == null) { - noSourceAttr.enter(); - found--; + found = 2; // next method attribute and class attribute + writeRNextMethod.execute(frame, nextMethodAttr); } } else { - found = 2; // next method attribute and class attribute - writeRNextMethod.execute(frame, nextMethodAttr); + found = 0; } writeRMethod.execute(frame, fdef); @@ -109,7 +114,7 @@ abstract class LoadMethod extends RBaseNode { } assert !fname.equals(RRuntime.R_LOAD_METHOD_NAME); RFunction ret; - if (moreAttributes.profile(found < fdef.getAttributes().size())) { + if (fdef.getAttributes() != null && moreAttributes.profile(found < fdef.getAttributes().size())) { RFunction currentFunction; REnvironment methodsEnv = (REnvironment) methodsEnvRead.execute(frame, REnvironment.getNamespaceRegistry().getFrame(regFrameAccessProfile)); if (loadMethodFind == null) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java index 44d51c9a1b090d243560b7404add7150eccc27f1..bfbd4f087e4544df2e55c244e8037c1c739631ae 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java @@ -13,7 +13,6 @@ package com.oracle.truffle.r.nodes.objects; import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder; - import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.access.AccessSlotNode; @@ -39,34 +38,29 @@ public abstract class NewObject extends RExternalBuiltinNode.Arg1 { @Child private GetFixedAttributeNode pckgAttrAccess = GetFixedAttributeNode.create(RRuntime.PCKG_ATTR_KEY); @Child private SetClassAttributeNode setClassAttrNode; - @Child private CastNode castStringScalar; - @Child private CastNode castLogicalScalar; - { - castStringScalar = newCastBuilder().asStringVector().findFirst(RRuntime.STRING_NA).buildCastNode(); - castLogicalScalar = newCastBuilder().asLogicalVector().findFirst(RRuntime.LOGICAL_NA).buildCastNode(); - } + @Child private CastNode castStringScalar = newCastBuilder().asStringVector().findFirst(RRuntime.STRING_NA).buildCastNode(); + @Child private CastNode castLogicalScalar = newCastBuilder().asLogicalVector().findFirst(RRuntime.LOGICAL_NA).buildCastNode(); static { Casts casts = new Casts(NewObject.class); // TODO: should we change the message to (incompatible) "Java level ..."? - casts.arg(0).mustNotBeNull(RError.NO_CALLER, RError.Message.GENERIC, "C level NEW macro called with null class definition pointer"); + casts.arg(0).mustNotBeNull(RError.Message.GENERIC, "C level NEW macro called with null class definition pointer"); } @Specialization protected Object doNewObject(Object classDef) { Object e = accessSlotVirtual.executeAccess(classDef, RRuntime.S_VIRTUAL); - if (((byte) castLogicalScalar.execute(e)) != RRuntime.LOGICAL_FALSE) { + if (((byte) castLogicalScalar.doCast(e)) != RRuntime.LOGICAL_FALSE) { e = accessSlotClassName.executeAccess(classDef, RRuntime.S_CLASSNAME); - throw RError.error(this, RError.Message.OBJECT_FROM_VIRTUAL, castStringScalar.execute(e)); + throw error(RError.Message.OBJECT_FROM_VIRTUAL, castStringScalar.doCast(e)); } e = accessSlotClassName.executeAccess(classDef, RRuntime.S_CLASSNAME); Object prototype = accessSlotPrototypeName.executeAccess(classDef, RRuntime.S_PROTOTYPE); Object value = duplicate.executeObject(prototype); assert value instanceof RAttributable; RAttributable valueAttr = (RAttributable) value; - if (valueAttr instanceof RS4Object || - (e instanceof RAttributable && ((RAttributable) e).getAttributes() != null && pckgAttrAccess.execute(((RAttributable) e).getAttributes()) != null)) { + if (valueAttr instanceof RS4Object || (e instanceof RAttributable && ((RAttributable) e).getAttributes() != null && pckgAttrAccess.execute(((RAttributable) e).getAttributes()) != null)) { if (setClassAttrNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java index 0290ce2ffd7ec6ee4102cdbf940166784e222b9f..009a71466344b12089f6fe90ff57ad6707b7c615 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java @@ -22,7 +22,6 @@ */ package com.oracle.truffle.r.nodes.primitive; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; @@ -234,8 +233,7 @@ public final class BinaryMapNode extends RBaseNode { private Object applyVectorized(RAbstractVector left, RAbstractVector leftCast, int leftLength, RAbstractVector right, RAbstractVector rightCast, int rightLength) { if (mayContainMetadata && (dimensionsProfile.profile(hasLeftDimNode.execute(left) && hasRightDimNode.execute(right)))) { if (differentDimensions(left, right)) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.NON_CONFORMABLE_ARRAYS); + throw error(RError.Message.NON_CONFORMABLE_ARRAYS); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/BypassNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/BypassNode.java deleted file mode 100644 index 59ae7e9a2c906bb286a56e2e9c677fb386fc7d0c..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/BypassNode.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * 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.nodes.unary; - -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.r.nodes.builtin.ArgumentMapper; -import com.oracle.truffle.r.nodes.builtin.casts.MessageData; -import com.oracle.truffle.r.nodes.builtin.casts.PipelineConfig; -import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode.ArgumentMapperFactory; -import com.oracle.truffle.r.nodes.unary.ConditionalMapNode.PipelineReturnException; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RNull; - -/** - * The node wraps the cast node created for a cast pipeline and handles {@code RNull} and - * {@code RMissing} according to {@link PipelineConfig}. Those values are either blocked or sent - * directly to either the 'find first' node with default value if there is any 'find first' node - * with default value in the pipeline or to directly to the builtin. - * - * There are several specialization capable of, on top of handling RNull/RMissing, sending a - * primitive value, e.g. integer, directly the first node after the 'find first' thus bypassing any - * other logic in between. - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public abstract class BypassNode extends CastNode { - - private final boolean isRNullBypassed; - private final MessageData nullMsg; - private final ArgumentMapper nullMapFn; - - private final boolean isRMissingBypassed; - private final MessageData missingMsg; - private final ArgumentMapper missingMapFn; - private final boolean noHead; - - /** - * This is the cast pipeline itself. - */ - @Child private CastNode wrappedHead; - - /** - * If there is a {@link FindFirstNode} in the pipeline with a default value, this will hold copy - * of it. - */ - @Child private CastNode directFindFirstNodeWithDefault; - - /** - * If there are some steps after the {@link FindFirstNode} in the cast pipeline, then this will - * hold copy of its first node (which can be chained to following nodes). - */ - @Child private CastNode afterFindFirst; - - protected BypassNode(PipelineConfig conf, CastNode wrappedHead, ArgumentMapperFactory mapperFactory, CastNode directFindFirstNodeWithDefault, - CastNode afterFindFirst) { - this.nullMapFn = conf.getNullMapper() == null ? null : mapperFactory.createMapper(conf.getNullMapper()); - this.isRNullBypassed = this.nullMapFn != null; - this.nullMsg = getMessage(isRNullBypassed, conf.getNullMessage(), conf); - - this.missingMapFn = conf.getMissingMapper() == null ? null : mapperFactory.createMapper(conf.getMissingMapper()); - this.isRMissingBypassed = this.missingMapFn != null; - this.missingMsg = getMessage(isRMissingBypassed, conf.getMissingMessage(), conf); - - this.wrappedHead = wrappedHead; - this.noHead = wrappedHead == null; - - this.directFindFirstNodeWithDefault = insertIfNotNull(directFindFirstNodeWithDefault); - this.afterFindFirst = insertIfNotNull(afterFindFirst); - } - - public final CastNode getWrappedHead() { - return wrappedHead; - } - - public final ArgumentMapper getNullMapper() { - return nullMapFn; - } - - public final ArgumentMapper getMissingMapper() { - return missingMapFn; - } - - protected final Object executeAfterFindFirst(Object value) { - if (afterFindFirst != null) { - try { - return afterFindFirst.execute(value); - } catch (PipelineReturnException ret) { - return ret.getResult(); - } - } else { - return value; - } - } - - private <T extends Node> T insertIfNotNull(T child) { - return child != null ? insert(child) : child; - } - - private MessageData getMessage(boolean isWarning, MessageData msg, PipelineConfig config) { - if (msg == null) { - return null; - } - - MessageData defaultValue = isWarning ? config.getDefaultWarning() : config.getDefaultError(); - MessageData result = isWarning ? msg : MessageData.getFirstNonNull(null, msg, defaultValue); - return result != null ? result.fixCallObj(this) : null; - } - - @Specialization - public Object bypassRNull(RNull x) { - if (isRNullBypassed) { - if (nullMsg != null) { - handleArgumentWarning(x, nullMsg.getCallObj(), nullMsg.getMessage(), nullMsg.getMessageArgs()); - } - return nullMapFn.map(x); - } else if (directFindFirstNodeWithDefault != null) { - return directFindFirstNodeWithDefault.execute(x); - } else if (nullMsg == null) { - // go to the pipeline - return handleOthers(x); - } else { - handleArgumentError(x, nullMsg.getCallObj(), nullMsg.getMessage(), nullMsg.getMessageArgs()); - return x; - } - } - - @Specialization - public Object bypassRMissing(RMissing x) { - if (isRMissingBypassed) { - if (missingMsg != null) { - handleArgumentWarning(x, missingMsg.getCallObj(), missingMsg.getMessage(), missingMsg.getMessageArgs()); - } - return missingMapFn.map(x); - } else if (directFindFirstNodeWithDefault != null) { - return directFindFirstNodeWithDefault.execute(x); - } else if (missingMsg == null) { - // go to the pipeline - return handleOthers(x); - } else { - handleArgumentError(x, missingMsg.getCallObj(), missingMsg.getMessage(), missingMsg.getMessageArgs()); - return x; - } - } - - @Specialization(guards = "isNotHandled(x)") - public Object handleOthers(Object x) { - try { - return noHead ? x : wrappedHead.execute(x); - } catch (PipelineReturnException ret) { - return ret.getResult(); - } - } - - protected boolean isNotHandled(Object x) { - return x != RNull.instance && x != RMissing.instance; - } - - public static CastNode create(PipelineConfig pipelineConfig, CastNode wrappedHead, ArgumentMapperFactory mapperFactory, CastNode directFindFirstNodeWithDefault) { - return BypassNodeGen.create(pipelineConfig, wrappedHead, mapperFactory, directFindFirstNodeWithDefault, null); - } - - public abstract static class BypassIntegerNode extends BypassNode { - public BypassIntegerNode(PipelineConfig pcb, CastNode wrappedHead, ArgumentMapperFactory mapperFactory, CastNode directFindFirstNode, - CastNode afterFindFirst) { - super(pcb, wrappedHead, mapperFactory, directFindFirstNode, afterFindFirst); - } - - @Specialization - protected Object bypassInteger(int x) { - return executeAfterFindFirst(x); - } - - @Override - protected boolean isNotHandled(Object x) { - return super.isNotHandled(x) && !(x instanceof Integer); - } - } - - public abstract static class BypassDoubleNode extends BypassNode { - public BypassDoubleNode(PipelineConfig pcb, CastNode wrappedHead, ArgumentMapperFactory mapperFactory, CastNode directFindFirstNode, - CastNode afterFindFirst) { - super(pcb, wrappedHead, mapperFactory, directFindFirstNode, afterFindFirst); - } - - @Specialization - public Object bypassDouble(double x) { - return executeAfterFindFirst(x); - } - - @Override - protected boolean isNotHandled(Object x) { - return super.isNotHandled(x) && !(x instanceof Integer); - } - } - - public abstract static class BypassStringNode extends BypassNode { - public BypassStringNode(PipelineConfig pcb, CastNode wrappedHead, ArgumentMapperFactory mapperFactory, CastNode directFindFirstNode, - CastNode afterFindFirst) { - super(pcb, wrappedHead, mapperFactory, directFindFirstNode, afterFindFirst); - } - - @Specialization - public Object bypassString(String x) { - return executeAfterFindFirst(x); - } - - @Override - protected boolean isNotHandled(Object x) { - return super.isNotHandled(x) && !(x instanceof String); - } - } - - public abstract static class BypassLogicalMapToBooleanNode extends BypassNode { - public BypassLogicalMapToBooleanNode(PipelineConfig pcb, CastNode wrappedHead, ArgumentMapperFactory mapperFactory, CastNode directFindFirstNode, - CastNode afterFindFirst) { - super(pcb, wrappedHead, mapperFactory, directFindFirstNode, afterFindFirst); - } - - @Specialization - public boolean bypassLogical(byte x) { - return RRuntime.fromLogical(x); - } - - @Override - protected boolean isNotHandled(Object x) { - return super.isNotHandled(x) && !(x instanceof Byte); - } - } -} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java index f136727e66301ca5e52345e87ad452d418b737a3..d94c36c1dc1816afdcf4ff0f4ebcca750a72ee7c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java @@ -45,7 +45,6 @@ import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.env.REnvironment; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; public abstract class CastBaseNode extends CastNode { @@ -62,8 +61,6 @@ public abstract class CastBaseNode extends CastNode { private final boolean preserveDimensions; private final boolean preserveAttributes; - protected final RBaseNode messageCallObj; - /** * GnuR provides several, sometimes incompatible, ways to coerce given value to given type. This * flag tells the cast node that it should behave in a way compatible with functions exposed by @@ -71,19 +68,11 @@ public abstract class CastBaseNode extends CastNode { */ private final boolean forRFFI; - protected CastBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallObj) { - this(preserveNames, preserveDimensions, preserveAttributes, false, messageCallObj); - } - protected CastBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - this(preserveNames, preserveDimensions, preserveAttributes, false, null); + this(preserveNames, preserveDimensions, preserveAttributes, false); } protected CastBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) { - this(preserveNames, preserveDimensions, preserveAttributes, forRFFI, null); - } - - protected CastBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, RBaseNode messageCallObj) { this.preserveNames = preserveNames; this.preserveDimensions = preserveDimensions; this.preserveAttributes = preserveAttributes; @@ -91,7 +80,6 @@ public abstract class CastBaseNode extends CastNode { if (preserveDimensions) { getDimNamesNode = GetDimNamesAttributeNode.create(); } - this.messageCallObj = messageCallObj == null ? this : messageCallObj; } public final boolean preserveNames() { @@ -110,7 +98,7 @@ public abstract class CastBaseNode extends CastNode { protected RError throwCannotCoerceListError(String type) { listCoercionErrorBranch.enter(); - throw RError.error(messageCallObj, RError.Message.LIST_COERCION, type); + throw error(RError.Message.LIST_COERCION, type); } protected int[] getPreservedDimensions(RAbstractContainer operand) { @@ -155,11 +143,11 @@ public abstract class CastBaseNode extends CastNode { protected Object doOtherDefault(Object mappedValue) { if (mappedValue instanceof REnvironment) { - throw RError.error(RError.SHOW_CALLER, RError.Message.ENVIRONMENTS_COERCE); + throw error(RError.Message.ENVIRONMENTS_COERCE); } else if (mappedValue instanceof RTypedValue) { - throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_COERCE, ((RTypedValue) mappedValue).getRType().getName(), getTargetType().getName()); + throw error(RError.Message.CANNOT_COERCE, ((RTypedValue) mappedValue).getRType().getName(), getTargetType().getName()); } else if (mappedValue instanceof TruffleObject) { - throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_COERCE, "truffleobject", getTargetType().getName()); + throw error(RError.Message.CANNOT_COERCE, "truffleobject", getTargetType().getName()); } else { throw RInternalError.shouldNotReachHere("unexpected value of type " + (mappedValue == null ? "null" : mappedValue.getClass())); } @@ -167,9 +155,9 @@ public abstract class CastBaseNode extends CastNode { protected Object doOtherRFFI(Object mappedValue) { if (mappedValue instanceof RTypedValue) { - RError.warning(RError.SHOW_CALLER2, Message.CANNOT_COERCE_RFFI, ((RTypedValue) mappedValue).getRType().getName(), getTargetType().getName()); + warning(Message.CANNOT_COERCE_RFFI, ((RTypedValue) mappedValue).getRType().getName(), getTargetType().getName()); } else if (mappedValue instanceof TruffleObject) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.CANNOT_COERCE, "truffleobject", getTargetType().getName()); + throw error(RError.Message.CANNOT_COERCE, "truffleobject", getTargetType().getName()); } return RNull.instance; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java index 3d8fb9edf3cb50b7c240b346f6b6ecd014af103c..88151421902d9518fbfeb23035b5ca4e27bcce3e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java @@ -37,6 +37,7 @@ import com.oracle.truffle.r.runtime.data.RComplexVector; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RRaw; import com.oracle.truffle.r.runtime.data.RRawVector; @@ -45,7 +46,6 @@ 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.RAbstractVector; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.ops.na.NACheck; import com.oracle.truffle.r.runtime.ops.na.NAProfile; @@ -63,12 +63,8 @@ public abstract class CastComplexNode extends CastBaseNode { public abstract Object executeComplex(Object o); - protected CastComplexNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) { - super(preserveNames, preserveDimensions, preserveAttributes, messageCallerObj); - } - protected CastComplexNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - this(preserveNames, preserveDimensions, preserveAttributes, false); + super(preserveNames, preserveDimensions, preserveAttributes); } protected CastComplexNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) { @@ -95,6 +91,11 @@ public abstract class CastComplexNode extends CastBaseNode { return RNull.instance; } + @Specialization + protected RMissing doMissing(@SuppressWarnings("unused") RMissing operand) { + return RMissing.instance; + } + @Specialization protected RComplex doInt(int operand) { naCheck.enable(operand); @@ -132,8 +133,7 @@ public abstract class CastComplexNode extends CastBaseNode { } RComplex result = RRuntime.string2complexNoCheck(operand); if (RRuntime.isNA(result) && !operand.equals(RRuntime.STRING_NaN)) { - warningBranch.enter(); - RError.warning(this, RError.Message.NA_INTRODUCED_COERCION); + warning(RError.Message.NA_INTRODUCED_COERCION); } return result; } @@ -200,7 +200,7 @@ public abstract class CastComplexNode extends CastBaseNode { ddata[index + 1] = complexValue.getImaginaryPart(); } if (warning) { - RError.warning(this, RError.Message.NA_INTRODUCED_COERCION); + warning(RError.Message.NA_INTRODUCED_COERCION); } RComplexVector ret = RDataFactory.createComplexVector(ddata, !seenNA, getPreservedDimensions(operand), getPreservedNames(operand)); preserveDimensionNames(operand, ret); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java index 6e1b66b74024f6c999d8c11e844bd43ffdb56519..9abeb67a8dbd105abcaf074d9907ab0aae07ff15 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java @@ -24,7 +24,6 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; @@ -33,7 +32,6 @@ import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RRaw; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.ops.na.NACheck; import com.oracle.truffle.r.runtime.ops.na.NAProfile; @@ -41,14 +39,9 @@ public abstract class CastDoubleBaseNode extends CastBaseNode { protected final NACheck naCheck = NACheck.create(); protected final NAProfile naProfile = NAProfile.create(); - protected final BranchProfile warningBranch = BranchProfile.create(); - - protected CastDoubleBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallObj) { - super(preserveNames, preserveDimensions, preserveAttributes, messageCallObj); - } protected CastDoubleBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - this(preserveNames, preserveDimensions, preserveAttributes, false); + super(preserveNames, preserveDimensions, preserveAttributes); } protected CastDoubleBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) { @@ -94,8 +87,7 @@ public abstract class CastDoubleBaseNode extends CastBaseNode { naCheck.enable(operand); double result = naCheck.convertComplexToDouble(operand, false); if (operand.getImaginaryPart() != 0.0) { - warningBranch.enter(); - RError.warning(messageCallObj, RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); + warning(RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); } return result; } @@ -114,8 +106,7 @@ public abstract class CastDoubleBaseNode extends CastBaseNode { } double result = RRuntime.string2doubleNoCheck(operand); if (RRuntime.isNA(result)) { - warningBranch.enter(); - RError.warning(messageCallObj, RError.Message.NA_INTRODUCED_COERCION); + warning(RError.Message.NA_INTRODUCED_COERCION); } return result; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java index d937c07eef513dd28ae555162996c52622b1a445..381bd14e90fbfdc5f491bcfad838e066c463adde 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java @@ -27,6 +27,7 @@ import java.util.function.IntToDoubleFunction; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; @@ -43,20 +44,15 @@ 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.RAbstractVector; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; public abstract class CastDoubleNode extends CastDoubleBaseNode { - protected CastDoubleNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - this(preserveNames, preserveDimensions, preserveAttributes, false); - } - protected CastDoubleNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) { super(preserveNames, preserveDimensions, preserveAttributes, forRFFI); } - protected CastDoubleNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) { - super(preserveNames, preserveDimensions, preserveAttributes, messageCallerObj); + protected CastDoubleNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { + super(preserveNames, preserveDimensions, preserveAttributes); } @Child private CastDoubleNode recursiveCastDouble; @@ -102,7 +98,8 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode { @Specialization protected RDoubleVector doStringVector(RStringVector operand, - @Cached("createBinaryProfile()") ConditionProfile emptyStringProfile) { + @Cached("createBinaryProfile()") ConditionProfile emptyStringProfile, + @Cached("create()") BranchProfile warningBranch) { naCheck.enable(operand); double[] ddata = new double[operand.getLength()]; boolean seenNA = false; @@ -126,7 +123,7 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode { ddata[i] = doubleValue; } if (warning) { - RError.warning(messageCallObj, RError.Message.NA_INTRODUCED_COERCION); + warning(RError.Message.NA_INTRODUCED_COERCION); } RDoubleVector ret = RDataFactory.createDoubleVector(ddata, !seenNA, getPreservedDimensions(operand), getPreservedNames(operand)); preserveDimensionNames(operand, ret); @@ -149,8 +146,7 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode { } } if (warning) { - warningBranch.enter(); - RError.warning(messageCallObj, RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); + warning(RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); } return vectorCopy(operand, ddata, naCheck.neverSeenNA()); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastExpressionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastExpressionNode.java index a5a4c01397428aa1bb6bb6e64d196c5e6f001906..c426860c0f999a558a6de930d99a750e1133cec7 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastExpressionNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastExpressionNode.java @@ -79,7 +79,7 @@ public abstract class CastExpressionNode extends CastBaseNode { @Specialization protected RExpression doFunction(RFunction value) { - throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_COERCE, value.isBuiltin() ? "builtin" : "closure", "expression"); + throw error(RError.Message.CANNOT_COERCE, value.isBuiltin() ? "builtin" : "closure", "expression"); } @Specialization @@ -108,8 +108,10 @@ public abstract class CastExpressionNode extends CastBaseNode { return RDataFactory.createExpression(new Object[]{obj}); } - public static CastExpressionNode createForRFFI(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - // RFFI coercion to list unlike others does not preserve names it seems + /** + * RFFI coercion to list unlike others does not preserve names it seems. + */ + public static CastExpressionNode createForRFFI() { return CastExpressionNodeGen.create(false, false, false, true); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java index 5a26f6d19895e8c6f35c4d243008cbc6b69d98e9..dc79c02b5f39ffc9223f8325157dececc441c961 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java @@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; @@ -34,26 +33,20 @@ import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RRaw; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.ops.na.NACheck; public abstract class CastIntegerBaseNode extends CastBaseNode { protected final NACheck naCheck = NACheck.create(); - protected final BranchProfile warningBranch = BranchProfile.create(); @Child private CastIntegerNode recursiveCastInteger; - protected CastIntegerBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - this(preserveNames, preserveDimensions, preserveAttributes, false); - } - protected CastIntegerBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) { super(preserveNames, preserveDimensions, preserveAttributes, forRFFI); } - protected CastIntegerBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallObj) { - super(preserveNames, preserveDimensions, preserveAttributes, messageCallObj); + protected CastIntegerBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { + super(preserveNames, preserveDimensions, preserveAttributes); } @Override @@ -64,7 +57,7 @@ public abstract class CastIntegerBaseNode extends CastBaseNode { protected Object castIntegerRecursive(Object o) { if (recursiveCastInteger == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - recursiveCastInteger = insert(CastIntegerNodeGen.create(preserveNames(), preserveDimensions(), preserveAttributes(), messageCallObj)); + recursiveCastInteger = insert(CastIntegerNodeGen.create(preserveNames(), preserveDimensions(), preserveAttributes())); } return recursiveCastInteger.executeInt(o); } @@ -95,8 +88,7 @@ public abstract class CastIntegerBaseNode extends CastBaseNode { naCheck.enable(operand); int result = naCheck.convertComplexToInt(operand, false); if (operand.getImaginaryPart() != 0.0) { - warningBranch.enter(); - RError.warning(messageCallObj, RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); + warning(RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); } return result; } @@ -110,8 +102,7 @@ public abstract class CastIntegerBaseNode extends CastBaseNode { } int result = RRuntime.string2intNoCheck(operand); if (RRuntime.isNA(result)) { - warningBranch.enter(); - RError.warning(messageCallObj, RError.Message.NA_INTRODUCED_COERCION); + warning(RError.Message.NA_INTRODUCED_COERCION); } return result; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java index b0310c602bddc67547b37ceca490cbd62324916d..7d46d80f99c8e1fd2db9a48b9a008a468348e836 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java @@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; @@ -42,23 +43,20 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.ops.na.NAProfile; public abstract class CastIntegerNode extends CastIntegerBaseNode { private final NAProfile naProfile = NAProfile.create(); - protected CastIntegerNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - this(preserveNames, preserveDimensions, preserveAttributes, false); - } + private final BranchProfile warningBranch = BranchProfile.create(); protected CastIntegerNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) { super(preserveNames, preserveDimensions, preserveAttributes, forRFFI); } - protected CastIntegerNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallObj) { - super(preserveNames, preserveDimensions, preserveAttributes, messageCallObj); + protected CastIntegerNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { + super(preserveNames, preserveDimensions, preserveAttributes); } public abstract Object executeInt(int o); @@ -126,8 +124,7 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode { } } if (warning) { - warningBranch.enter(); - RError.warning(messageCallObj, RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); + warning(RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); } return vectorCopy(operand, idata, naCheck.neverSeenNA()); } @@ -158,7 +155,7 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode { idata[i] = intValue; } if (warning) { - RError.warning(messageCallObj, RError.Message.NA_INTRODUCED_COERCION); + warning(RError.Message.NA_INTRODUCED_COERCION); } return vectorCopy(operand, idata, !seenNA); } @@ -230,7 +227,7 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode { } public static CastIntegerNode create() { - return CastIntegerNodeGen.create(true, true, true, null); + return CastIntegerNodeGen.create(true, true, true); } public static CastIntegerNode createForRFFI(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { @@ -238,10 +235,6 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode { } public static CastIntegerNode createNonPreserving() { - return CastIntegerNodeGen.create(false, false, false, null); - } - - public static CastIntegerNode createPreserveNames() { - return CastIntegerNodeGen.create(false, false, false, null); + return CastIntegerNodeGen.create(false, false, false); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java index 1fc21b1956a3090baa9154e67dd895db82e8752f..9a868b06d2ba24581bfec447e8c02de0076bfddc 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java @@ -26,7 +26,9 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; 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.ValueProfile; import com.oracle.truffle.r.nodes.attributes.ArrayAttributeNode; import com.oracle.truffle.r.nodes.attributes.SetAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode; @@ -36,6 +38,7 @@ import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RAttributesLayout; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RFunction; +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.RNull; @@ -80,10 +83,12 @@ public abstract class CastListNode extends CastBaseNode { } @Specialization - protected RList doAbstractVector(RAbstractVector operand) { - Object[] data = new Object[operand.getLength()]; + protected RList doAbstractVector(RAbstractVector operand, + @Cached("createClassProfile()") ValueProfile vectorClassProfile) { + RAbstractVector profiledOperand = vectorClassProfile.profile(operand); + Object[] data = new Object[profiledOperand.getLength()]; for (int i = 0; i < data.length; i++) { - data[i] = operand.getDataAtAsObject(i); + data[i] = profiledOperand.getDataAtAsObject(i); } RList ret = RDataFactory.createList(data, getPreservedDimensions(operand), getPreservedNames(operand)); preserveDimensionNames(operand, ret); @@ -144,6 +149,16 @@ public abstract class CastListNode extends CastBaseNode { return RDataFactory.createList(new Object[]{s}); } + @Specialization + protected RList doRInterop(RInteropScalar ri) { + return RDataFactory.createList(new Object[]{ri}); + } + + @Specialization(guards = {"isForeignObject(to)"}) + protected RList doForeignObject(TruffleObject to) { + return RDataFactory.createList(new Object[]{to}); + } + public static CastListNode create() { return CastListNodeGen.create(true, true, true); } @@ -151,4 +166,8 @@ public abstract class CastListNode extends CastBaseNode { public static CastListNode createForRFFI(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { return CastListNodeGen.create(preserveNames, preserveDimensions, preserveAttributes, true); } + + protected boolean isForeignObject(TruffleObject to) { + return RRuntime.isForeignObject(to); + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalBaseNode.java index 94f484b2fcb70f5c38f0cf120146a5e8d0db7066..a01f4bdf4da8befd7a329a43ad79d321ac821dbf 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalBaseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalBaseNode.java @@ -27,23 +27,18 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RRaw; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.ops.na.NACheck; public abstract class CastLogicalBaseNode extends CastBaseNode { protected final NACheck naCheck = NACheck.create(); - protected CastLogicalBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - this(preserveNames, preserveDimensions, preserveAttributes, false); - } - protected CastLogicalBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) { super(preserveNames, preserveDimensions, preserveAttributes, forRFFI); } - protected CastLogicalBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallObj) { - super(preserveNames, preserveDimensions, preserveAttributes, messageCallObj); + protected CastLogicalBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { + super(preserveNames, preserveDimensions, preserveAttributes); } @Override diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java index 6f15ddd3fc0adfaf0925225098145b3806ab1b5b..79d3635e48cbea9dd3adc96bb69d3959cf3a7bcc 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java @@ -41,7 +41,6 @@ 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.RAbstractVector; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.ops.na.NAProfile; public abstract class CastLogicalNode extends CastLogicalBaseNode { @@ -51,12 +50,8 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode { @Child private CastLogicalNode recursiveCastLogical; @Child private InheritsCheckNode inheritsFactorCheck; - protected CastLogicalNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallObj) { - super(preserveNames, preserveDimensions, preserveAttributes, messageCallObj); - } - protected CastLogicalNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { - this(preserveNames, preserveDimensions, preserveAttributes, false); + super(preserveNames, preserveDimensions, preserveAttributes); } protected CastLogicalNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) { @@ -187,11 +182,6 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode { return ret; } - @Specialization - protected RArgsValuesAndNames doArgsValueAndNames(RArgsValuesAndNames values) { - return values; - } - @Specialization protected RMissing doMissing(RMissing missing) { return missing; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java index e1cf552841438ed5a9db695474689766d2054c7b..9e3f0995601b59a7a0ed861e07558d0a0af1a2f8 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.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 @@ -25,9 +25,10 @@ package com.oracle.truffle.r.nodes.unary; import java.util.Arrays; import java.util.function.Function; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.profiles.ValueProfile; +import com.oracle.truffle.r.nodes.builtin.casts.MessageData; import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; /** * Cast nodes behave like unary nodes, but in many cases it is useful to have a specific type for @@ -38,10 +39,18 @@ public abstract class CastNode extends UnaryNode { private static boolean isTesting = false; private static String lastWarning; + private final ValueProfile classProfile = ValueProfile.createClassProfile(); + public static void testingMode() { isTesting = true; } + public Object doCast(Object value) { + return execute(classProfile.profile(value)); + } + + protected abstract Object execute(Object value); + /** * For testing purposes only, returns the last warning message (only when {@link #testingMode()} * was invoked before). @@ -50,30 +59,13 @@ public abstract class CastNode extends UnaryNode { return lastWarning; } - @TruffleBoundary - protected static void handleArgumentError(Object arg, RBaseNode callObj, RError.Message message, Object[] messageArgs) { - if (isTesting) { - throw new IllegalArgumentException(String.format(message.message, substituteArgPlaceholder(arg, messageArgs))); - } else { - throw RError.error(callObj, message, substituteArgPlaceholder(arg, messageArgs)); - } - } - - @TruffleBoundary - protected static void handleArgumentWarning(Object arg, RBaseNode callObj, RError.Message message, Object[] messageArgs) { - if (message == null) { - return; - } - - if (isTesting) { - lastWarning = String.format(message.message, substituteArgPlaceholder(arg, messageArgs)); - } else { - RError.warning(callObj, message, substituteArgPlaceholder(arg, messageArgs)); - } + public static void clearLastWarning() { + lastWarning = null; } @SuppressWarnings({"unchecked"}) - public static Object[] substituteArgPlaceholder(Object arg, Object[] messageArgs) { + private static Object[] substituteArgs(Object arg, MessageData message) { + Object[] messageArgs = message.getMessageArgs(); Object[] newMsgArgs = Arrays.copyOf(messageArgs, messageArgs.length); for (int i = 0; i < messageArgs.length; i++) { @@ -82,7 +74,29 @@ public abstract class CastNode extends UnaryNode { newMsgArgs[i] = ((Function<Object, Object>) msgArg).apply(arg); } } - return newMsgArgs; } + + protected RuntimeException handleArgumentError(Object arg, MessageData message) { + CompilerDirectives.transferToInterpreter(); + Object[] args = substituteArgs(arg, message); + if (isTesting) { + throw new IllegalArgumentException(String.format(message.getMessage().message, args)); + } else { + throw RError.error(getErrorContext(), message.getMessage(), args); + } + } + + protected void handleArgumentWarning(Object arg, MessageData message) { + CompilerDirectives.transferToInterpreter(); + if (message == null) { + return; + } + Object[] args = substituteArgs(arg, message); + if (isTesting) { + lastWarning = String.format(message.getMessage().message, args); + } else { + RError.warning(getErrorContext(), message.getMessage(), args); + } + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java index 9471d88d7a054c98afd9c2a79edc12bb6cc5b4b3..c66438279a68fe416dead3725adc170253c3d9ac 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java @@ -34,6 +34,7 @@ import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RComplexVector; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RRaw; import com.oracle.truffle.r.runtime.data.RRawVector; @@ -86,10 +87,14 @@ public abstract class CastRawNode extends CastBaseNode { return RNull.instance; } + @Specialization + protected RMissing doMissing(@SuppressWarnings("unused") RMissing operand) { + return RMissing.instance; + } + private RRaw checkOutOfRange(int operand, int intResult) { if (intResult != operand) { - warningBranch.enter(); - RError.warning(this, RError.Message.OUT_OF_RANGE); + warning(RError.Message.OUT_OF_RANGE); return RDataFactory.createRaw((byte) 0); } return RDataFactory.createRaw((byte) intResult); @@ -111,8 +116,7 @@ public abstract class CastRawNode extends CastBaseNode { protected RRaw doComplex(RComplex operand) { int intResult = RRuntime.complex2rawIntValue(operand); if (operand.getImaginaryPart() != 0) { - warningBranch.enter(); - RError.warning(this, RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); + warning(RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); } return checkOutOfRange((int) operand.getRealPart(), intResult); } @@ -139,14 +143,12 @@ public abstract class CastRawNode extends CastBaseNode { } else { intValue = RRuntime.string2intNoCheck(operand); if (RRuntime.isNA(intValue)) { - warningBranch.enter(); - RError.warning(this, RError.Message.NA_INTRODUCED_COERCION); + warning(RError.Message.NA_INTRODUCED_COERCION); } } int intRawValue = RRuntime.int2rawIntValue(intValue); if (intRawValue != intValue) { - warningBranch.enter(); - RError.warning(this, RError.Message.OUT_OF_RANGE); + warning(RError.Message.OUT_OF_RANGE); return RRaw.valueOf((byte) 0); } return RRaw.valueOf((byte) intRawValue); @@ -177,7 +179,7 @@ public abstract class CastRawNode extends CastBaseNode { bdata[i] = (byte) intRawValue; } if (warning) { - RError.warning(this, RError.Message.OUT_OF_RANGE); + warning(RError.Message.OUT_OF_RANGE); } return vectorCopy(operand, bdata); } @@ -197,7 +199,7 @@ public abstract class CastRawNode extends CastBaseNode { bdata[i] = (byte) intRawValue; } if (warning) { - RError.warning(this, RError.Message.OUT_OF_RANGE); + warning(RError.Message.OUT_OF_RANGE); } return vectorCopy(operand, bdata); } @@ -234,10 +236,10 @@ public abstract class CastRawNode extends CastBaseNode { bdata[i] = (byte) intValue; } if (naCoercionWarning) { - RError.warning(this, RError.Message.NA_INTRODUCED_COERCION); + warning(RError.Message.NA_INTRODUCED_COERCION); } if (outOfRangeWarning) { - RError.warning(this, RError.Message.OUT_OF_RANGE); + warning(RError.Message.OUT_OF_RANGE); } return vectorCopy(operand, bdata); } @@ -262,10 +264,10 @@ public abstract class CastRawNode extends CastBaseNode { bdata[i] = (byte) intRawValue; } if (imaginaryDiscardedWarning) { - RError.warning(this, RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); + warning(RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); } if (outOfRangeWarning) { - RError.warning(this, RError.Message.OUT_OF_RANGE); + warning(RError.Message.OUT_OF_RANGE); } return vectorCopy(operand, bdata); } @@ -286,7 +288,7 @@ public abstract class CastRawNode extends CastBaseNode { bdata[i] = (byte) intRawValue; } if (warning) { - RError.warning(this, RError.Message.OUT_OF_RANGE); + warning(RError.Message.OUT_OF_RANGE); } return vectorCopy(operand, bdata); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java index a59b45866a9f896aba4c630d879592f5af370bc3..66cc1de16106911653b8e49691134ee0778d02fb 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java @@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RLanguage; @@ -65,8 +66,10 @@ public abstract class CastStringNode extends CastStringBaseNode { } @Specialization - protected RStringVector doAbstractContainer(RAbstractContainer operand, + protected RStringVector doAbstractContainer(RAbstractContainer operandIn, + @Cached("createClassProfile()") ValueProfile operandProfile, @Cached("createBinaryProfile()") ConditionProfile isLanguageProfile) { + RAbstractContainer operand = operandProfile.profile(operandIn); String[] sdata = new String[operand.getLength()]; // conversions to character will not introduce new NAs for (int i = 0; i < operand.getLength(); i++) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java index 31b0fea74e35ffce8cef8529677f9387887efbae..2b45b6639ae5045f8d4941d354b0fc0bf958e45a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.unary; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.runtime.RError; @@ -62,7 +63,7 @@ public abstract class CastSymbolNode extends CastBaseNode { @Specialization protected RSymbol doNull(@SuppressWarnings("unused") RNull value) { - throw RError.error(this, RError.Message.INVALID_TYPE_LENGTH, "symbol", 0); + throw error(RError.Message.INVALID_TYPE_LENGTH, "symbol", 0); } @Specialization @@ -88,7 +89,10 @@ public abstract class CastSymbolNode extends CastBaseNode { @Specialization @TruffleBoundary protected RSymbol doString(String value) { - // TODO: see if this is going to hit us performance-wise + if (value.isEmpty()) { + CompilerDirectives.transferToInterpreter(); + throw error(RError.Message.ZERO_LENGTH_VARIABLE); + } return RDataFactory.createSymbolInterned(value); } @@ -117,9 +121,9 @@ public abstract class CastSymbolNode extends CastBaseNode { @TruffleBoundary protected RSymbol doEmptyVector(RAbstractVector vector) { if (vector instanceof RList) { - throw RError.error(this, RError.Message.INVALID_TYPE_LENGTH, "symbol", 0); + throw error(RError.Message.INVALID_TYPE_LENGTH, "symbol", 0); } else { - throw RError.error(this, Message.INVALID_DATA_OF_TYPE_TOO_SHORT, vector.getRType().getName(), 0); + throw error(Message.INVALID_DATA_OF_TYPE_TOO_SHORT, vector.getRType().getName(), 0); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToAttributableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToAttributableNode.java index 790a649b001709dd8904deb6888618f7d3e492fe..9dd87e625f69225c24e6dfe2417b986fe80a0731 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToAttributableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToAttributableNode.java @@ -51,14 +51,12 @@ public abstract class CastToAttributableNode extends CastBaseNode { } @Specialization - @SuppressWarnings("unused") - protected RNull cast(RNull rnull) { + protected RNull cast(@SuppressWarnings("unused") RNull rnull) { return RNull.instance; } @Specialization - @SuppressWarnings("unused") - protected RMissing cast(RMissing rmissing) { + protected RMissing cast(@SuppressWarnings("unused") RMissing rmissing) { return RMissing.instance; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ChainedCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ChainedCastNode.java index f57e27e31b17d73474aea021360ff032bf113019..ba239b34feb2c0427d0447e3e5169347a20a3826 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ChainedCastNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ChainedCastNode.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 @@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.nodes.NodeInfo; +import com.oracle.truffle.r.nodes.unary.ConditionalMapNode.PipelineReturnException; @NodeInfo(cost = NodeCost.NONE) public final class ChainedCastNode extends CastNode { @@ -33,22 +34,28 @@ public final class ChainedCastNode extends CastNode { CastNode create(); } - private final CastNodeFactory firstCastFact; - private final CastNodeFactory secondCastFact; - @Child private CastNode firstCast; @Child private CastNode secondCast; - public ChainedCastNode(CastNodeFactory firstCastFact, CastNodeFactory secondCastFact) { - this.firstCastFact = firstCastFact; - this.secondCastFact = secondCastFact; - this.firstCast = firstCastFact.create(); - this.secondCast = secondCastFact.create(); + private final boolean isFirstNode; + + public ChainedCastNode(CastNode firstCast, CastNode secondCast, boolean isFirstNode) { + this.firstCast = firstCast; + this.secondCast = secondCast; + this.isFirstNode = isFirstNode; } @Override public Object execute(Object value) { - return secondCast.execute(firstCast.execute(value)); + if (isFirstNode) { + try { + return secondCast.execute(firstCast.execute(value)); + } catch (PipelineReturnException ex) { + return ex.getResult(); + } + } else { + return secondCast.execute(firstCast.execute(value)); + } } public CastNode getFirstCast() { @@ -58,12 +65,4 @@ public final class ChainedCastNode extends CastNode { public CastNode getSecondCast() { return secondCast; } - - public CastNodeFactory getFirstCastFact() { - return firstCastFact; - } - - public CastNodeFactory getSecondCastFact() { - return secondCastFact; - } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConditionalMapNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConditionalMapNode.java index 081b1bc06a596aea8bd5fd1900d4cbbb34aaa99a..862aff020da853cf54a447a3bf17cdb4192dd790 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConditionalMapNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConditionalMapNode.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.unary; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.nodes.ControlFlowException; import com.oracle.truffle.api.profiles.ConditionProfile; @@ -31,8 +32,7 @@ import com.oracle.truffle.r.runtime.data.RNull; public abstract class ConditionalMapNode extends CastNode { - private final ArgumentFilter<?, ?> argFilter; - private final ConditionProfile conditionProfile = ConditionProfile.createBinaryProfile(); + private final ArgumentFilter<Object, Object> argFilter; private final boolean resultForNull; private final boolean resultForMissing; private final boolean returns; @@ -40,8 +40,7 @@ public abstract class ConditionalMapNode extends CastNode { @Child private CastNode trueBranch; @Child private CastNode falseBranch; - protected ConditionalMapNode(ArgumentFilter<?, ?> argFilter, CastNode trueBranch, CastNode falseBranch, boolean resultForNull, - boolean resultForMissing, boolean returns) { + protected ConditionalMapNode(ArgumentFilter<Object, Object> argFilter, CastNode trueBranch, CastNode falseBranch, boolean resultForNull, boolean resultForMissing, boolean returns) { this.argFilter = argFilter; this.trueBranch = trueBranch; this.falseBranch = falseBranch; @@ -50,31 +49,12 @@ public abstract class ConditionalMapNode extends CastNode { this.returns = returns; } - public static ConditionalMapNode create(ArgumentFilter<?, ?> argFilter, CastNode trueBranch, - CastNode falseBranch, boolean resultForNull, - boolean resultForMissing, boolean returns) { + public static ConditionalMapNode create(ArgumentFilter<Object, Object> argFilter, CastNode trueBranch, CastNode falseBranch, boolean resultForNull, boolean resultForMissing, boolean returns) { return ConditionalMapNodeGen.create(argFilter, trueBranch, falseBranch, resultForNull, resultForMissing, returns); } - public boolean isReturns() { - return returns; - } - - public ArgumentFilter<?, ?> getFilter() { - return argFilter; - } - - public CastNode getTrueBranch() { - return trueBranch; - } - - public CastNode getFalseBranch() { - return falseBranch; - } - - @Specialization - protected Object executeNull(RNull x) { - if (resultForNull) { + private Object executeConditional(boolean isTrue, Object x) { + if (isTrue) { Object result = trueBranch == null ? x : trueBranch.execute(x); if (returns) { throw new PipelineReturnException(result); @@ -87,36 +67,19 @@ public abstract class ConditionalMapNode extends CastNode { } @Specialization - protected Object executeMissing(RMissing x) { - if (resultForMissing) { - Object result = trueBranch == null ? x : trueBranch.execute(x); - if (returns) { - throw new PipelineReturnException(result); - } else { - return result; - } - } else { - return falseBranch == null ? x : falseBranch.execute(x); - } + protected Object executeNull(RNull x) { + return executeConditional(resultForNull, x); } - protected static boolean isNotNullOrMissing(Object x) { - return x != RNull.instance && x != RMissing.instance; + @Specialization + protected Object executeMissing(RMissing x) { + return executeConditional(resultForMissing, x); } - @Specialization(guards = "isNotNullOrMissing(x)") - @SuppressWarnings("unchecked") - protected Object executeRest(Object x) { - if (conditionProfile.profile(((ArgumentFilter<Object, Object>) argFilter).test(x))) { - Object result = trueBranch == null ? x : trueBranch.execute(x); - if (returns) { - throw new PipelineReturnException(result); - } else { - return result; - } - } else { - return falseBranch == null ? x : falseBranch.execute(x); - } + @Specialization(guards = {"!isRNull(x)", "!isRMissing(x)"}) + protected Object executeRest(Object x, + @Cached("createBinaryProfile()") ConditionProfile conditionProfile) { + return executeConditional(conditionProfile.profile(argFilter.test(x)), x); } @SuppressWarnings("serial") diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java index 9a4fe5e0466288eefe2b0e64e086afb1beebc916..42edcbb3ac9b8481281e8f7f631dbf241da2c6dd 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java @@ -48,7 +48,6 @@ public abstract class ConvertBooleanNode extends RNode { private final NAProfile naProfile = NAProfile.create(); private final BranchProfile invalidElementCountBranch = BranchProfile.create(); - private final BranchProfile errorBranch = BranchProfile.create(); @Override public final Object execute(VirtualFrame frame) { @@ -64,13 +63,13 @@ public abstract class ConvertBooleanNode extends RNode { @Specialization protected byte doNull(@SuppressWarnings("unused") RNull value) { - throw RError.error(this, RError.Message.LENGTH_ZERO); + throw error(RError.Message.LENGTH_ZERO); } @Specialization protected byte doInt(int value) { if (naProfile.isNA(value)) { - throw RError.error(this, RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL); + throw error(RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL); } return RRuntime.int2logicalNoCheck(value); } @@ -78,7 +77,7 @@ public abstract class ConvertBooleanNode extends RNode { @Specialization protected byte doDouble(double value) { if (naProfile.isNA(value)) { - throw RError.error(this, RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL); + throw error(RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL); } return RRuntime.double2logicalNoCheck(value); } @@ -86,7 +85,7 @@ public abstract class ConvertBooleanNode extends RNode { @Specialization protected byte doLogical(byte value) { if (naProfile.isNA(value)) { - throw RError.error(this, RError.Message.NA_UNEXP); + throw error(RError.Message.NA_UNEXP); } return value; } @@ -94,7 +93,7 @@ public abstract class ConvertBooleanNode extends RNode { @Specialization protected byte doComplex(RComplex value) { if (naProfile.isNA(value)) { - throw RError.error(this, RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL); + throw error(RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL); } return RRuntime.complex2logicalNoCheck(value); } @@ -103,7 +102,7 @@ public abstract class ConvertBooleanNode extends RNode { protected byte doString(String value) { byte logicalValue = RRuntime.string2logicalNoCheck(value); if (naProfile.isNA(logicalValue)) { - throw RError.error(this, RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL); + throw error(RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL); } return logicalValue; } @@ -117,10 +116,9 @@ public abstract class ConvertBooleanNode extends RNode { if (value.getLength() != 1) { invalidElementCountBranch.enter(); if (value.getLength() == 0) { - errorBranch.enter(); - throw RError.error(this, RError.Message.LENGTH_ZERO); + throw error(RError.Message.LENGTH_ZERO); } else { - RError.warning(this, RError.Message.LENGTH_GT_1); + warning(RError.Message.LENGTH_GT_1); } } } @@ -164,7 +162,7 @@ public abstract class ConvertBooleanNode extends RNode { @Specialization protected byte doRawVector(RList value) { checkLength(value); - throw RError.error(this, RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL); + throw error(RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL); } public static ConvertBooleanNode create(RSyntaxNode node) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FilterNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FilterNode.java index 779c4f14778a5d45ac3a99d893c6063c570ded1c..cc825844e87aa979932fe2b5022e9e2edf112834 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FilterNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FilterNode.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.unary; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; @@ -29,62 +30,45 @@ import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode; import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNodeGen; import com.oracle.truffle.r.nodes.builtin.ArgumentFilter; -import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.nodes.builtin.casts.MessageData; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; -@SuppressWarnings({"rawtypes", "unchecked"}) public abstract class FilterNode extends CastNode { - private final ArgumentFilter filter; - private final RError.Message message; - private final RBaseNode callObj; - private final Object[] messageArgs; - private final boolean boxPrimitives; + private final ArgumentFilter<Object, Object> filter; + private final MessageData message; private final boolean isWarning; private final boolean resultForNull; private final boolean resultForMissing; private final BranchProfile warningProfile = BranchProfile.create(); - private final ConditionProfile conditionProfile = ConditionProfile.createBinaryProfile(); private final ValueProfile valueProfile = ValueProfile.createClassProfile(); - @Child private BoxPrimitiveNode boxPrimitiveNode = BoxPrimitiveNodeGen.create(); + @Child private BoxPrimitiveNode boxPrimitiveNode; - protected FilterNode(ArgumentFilter<?, ?> filter, boolean isWarning, RBaseNode callObj, RError.Message message, Object[] messageArgs, boolean boxPrimitives, boolean resultForNull, - boolean resultForMissing) { + protected FilterNode(ArgumentFilter<Object, Object> filter, boolean isWarning, MessageData message, boolean boxPrimitives, boolean resultForNull, boolean resultForMissing) { this.filter = filter; this.isWarning = isWarning; - this.callObj = callObj == null ? this : callObj; + assert message != null; this.message = message; - this.messageArgs = messageArgs; - this.boxPrimitives = boxPrimitives; + this.boxPrimitiveNode = boxPrimitives ? BoxPrimitiveNodeGen.create() : null; this.resultForNull = resultForNull; this.resultForMissing = resultForMissing; } - public static FilterNode create(ArgumentFilter<?, ?> filter, boolean isWarning, RBaseNode callObj, RError.Message message, Object[] messageArgs, boolean boxPrimitives, boolean resultForNull, - boolean resultForMissing) { - return FilterNodeGen.create(filter, isWarning, callObj, message, messageArgs, boxPrimitives, resultForNull, resultForMissing); - } - - public ArgumentFilter getFilter() { - return filter; - } - - public boolean isWarning() { - return isWarning; + public static FilterNode create(ArgumentFilter<Object, Object> filter, boolean isWarning, MessageData message, boolean boxPrimitives, boolean resultForNull, boolean resultForMissing) { + return FilterNodeGen.create(filter, isWarning, message, boxPrimitives, resultForNull, resultForMissing); } private void handleMessage(Object x) { if (isWarning) { if (message != null) { warningProfile.enter(); - handleArgumentWarning(x, callObj, message, messageArgs); + handleArgumentWarning(x, message); } } else { - handleArgumentError(x, callObj, message, messageArgs); + throw handleArgumentError(x, message); } } @@ -104,12 +88,9 @@ public abstract class FilterNode extends CastNode { return x; } - protected static boolean isNotNullOrMissing(Object x) { - return x != RNull.instance && x != RMissing.instance; - } - - @Specialization(guards = "isNotNullOrMissing(x)") - public Object executeRest(Object x) { + @Specialization(guards = {"!isRNull(x)", "!isRMissing(x)"}) + public Object executeRest(Object x, + @Cached("createBinaryProfile()") ConditionProfile conditionProfile) { if (!conditionProfile.profile(evalCondition(valueProfile.profile(x)))) { handleMessage(x); } @@ -117,7 +98,7 @@ public abstract class FilterNode extends CastNode { } protected boolean evalCondition(Object x) { - Object y = boxPrimitives ? boxPrimitiveNode.execute(x) : x; + Object y = boxPrimitiveNode != null ? boxPrimitiveNode.execute(x) : x; return filter.test(y); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FindFirstNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FindFirstNode.java index 2aac18c22c465e9b9b6c91c19ce0699d909efbda..5fa42384ef4793855ae2ec607af54354b9550e16 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FindFirstNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FindFirstNode.java @@ -24,36 +24,31 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; -import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.nodes.builtin.casts.MessageData; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; public abstract class FindFirstNode extends CastNode { private final Class<?> elementClass; - private final RBaseNode callObj; - private final RError.Message message; - private final Object[] messageArgs; + private final MessageData message; private final Object defaultValue; private final BranchProfile warningProfile = BranchProfile.create(); - protected FindFirstNode(Class<?> elementClass, RBaseNode callObj, RError.Message message, Object[] messageArgs, Object defaultValue) { - this.callObj = callObj == null ? this : callObj; + protected FindFirstNode(Class<?> elementClass, MessageData message, Object defaultValue) { this.elementClass = elementClass; this.defaultValue = defaultValue; this.message = message; - this.messageArgs = messageArgs; } protected FindFirstNode(Class<?> elementClass, Object defaultValue) { - this(elementClass, null, null, null, defaultValue); + this(elementClass, null, defaultValue); } - public static FindFirstNode create(Class<?> elementClass, RBaseNode callObj, RError.Message message, Object... args) { - return FindFirstNodeGen.create(elementClass, callObj, message, args, null); + public static FindFirstNode create(Class<?> elementClass, MessageData message) { + return FindFirstNodeGen.create(elementClass, message, null); } public Class<?> getElementClass() { @@ -88,12 +83,11 @@ public abstract class FindFirstNode extends CastNode { if (defaultValue != null) { if (message != null) { warningProfile.enter(); - handleArgumentWarning(x, callObj, message, messageArgs); + handleArgumentWarning(x, message); } return defaultValue; } else { - handleArgumentError(x, callObj, message, messageArgs); - return null; + throw handleArgumentError(x, message); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstBooleanNode.java index 4a0c825550185fa9cde0d5625784d4db33747226..ef815934332625b14ffc8d617b111766db7a9c61 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstBooleanNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstBooleanNode.java @@ -58,7 +58,7 @@ public abstract class FirstBooleanNode extends CastNode { protected boolean firstScalar(byte argument) { if (RRuntime.isNA(argument)) { CompilerDirectives.transferToInterpreter(); - throw RError.error(this, invalidValueName == null ? Message.NA_UNEXP : Message.INVALID_VALUE, invalidValueName); + throw error(invalidValueName == null ? Message.NA_UNEXP : Message.INVALID_VALUE, invalidValueName); } return RRuntime.fromLogical(argument); } @@ -67,7 +67,7 @@ public abstract class FirstBooleanNode extends CastNode { if (lengthNotOneProfile.profile(argument.getLength() != 1)) { if (argument.getLength() == 0) { CompilerDirectives.transferToInterpreter(); - throw RError.error(this, invalidValueName == null ? Message.LENGTH_ZERO : Message.INVALID_VALUE, invalidValueName); + throw error(invalidValueName == null ? Message.LENGTH_ZERO : Message.INVALID_VALUE, invalidValueName); } else { warningProfile.enter(); if (invalidValueName == null) { @@ -104,6 +104,6 @@ public abstract class FirstBooleanNode extends CastNode { @Fallback protected boolean fallback(@SuppressWarnings("unused") Object argument) { CompilerDirectives.transferToInterpreter(); - throw RError.error(this, invalidValueName == null ? Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL : Message.INVALID_VALUE, invalidValueName); + throw error(invalidValueName == null ? Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL : Message.INVALID_VALUE, invalidValueName); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstIntNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstIntNode.java index 54d04e8c92348567801b540b933141b02fc5eb73..3df79d197dad0bc239f1a12539ee4babbcf55043 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstIntNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstIntNode.java @@ -23,7 +23,6 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; @@ -46,7 +45,6 @@ public abstract class FirstIntNode extends CastNode { public abstract int executeInt(Object value); private final ConditionProfile lengthOneProfile = ConditionProfile.createBinaryProfile(); - private final BranchProfile errorProfile = BranchProfile.create(); @Specialization protected int firstScalar(int argument) { @@ -62,8 +60,7 @@ public abstract class FirstIntNode extends CastNode { return defaultValue; } } else if (emptyError != null && argument.getLength() == 0) { - errorProfile.enter(); - throw RError.error(this, emptyError, argumentName); + throw error(emptyError, argumentName); } } return argument.getDataAt(0); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstStringNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstStringNode.java index a1672bbea11b297a6b12a90dc584590e27cb9335..e0bde5a1048ab217bfef1bb4802ffd905e9bd4cb 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstStringNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstStringNode.java @@ -24,8 +24,6 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.profiles.BranchProfile; -import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @@ -40,9 +38,6 @@ public abstract class FirstStringNode extends CastNode { this.argumentName = argumentName; } - private final ConditionProfile lengthOneProfile = ConditionProfile.createBinaryProfile(); - private final BranchProfile errorProfile = BranchProfile.create(); - public final String executeString(Object argument) { return (String) execute(argument); } @@ -54,16 +49,15 @@ public abstract class FirstStringNode extends CastNode { @Specialization(replaces = "firstScalar") protected String firstVector(RAbstractStringVector argument) { - if (!lengthOneProfile.profile(argument.getLength() == 1)) { - errorProfile.enter(); - throw RError.error(RError.SHOW_CALLER, emptyError, argumentName); + if (argument.getLength() != 1) { + throw error(emptyError, argumentName); } return argument.getDataAt(0); } @Fallback protected String firstVectorFallback(@SuppressWarnings("unused") Object argument) { - throw RError.error(RError.SHOW_CALLER, emptyError, argumentName); + throw error(emptyError, argumentName); } public static FirstStringNode createWithError(RError.Message emptyError, String argumentName) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java index 9505d3897be12a924c419e3002310f3456922879..9e70abd64665b293003018354688c1fc2cbe9285 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,55 +22,53 @@ */ package com.oracle.truffle.r.nodes.unary; -import com.oracle.truffle.api.dsl.NodeChild; +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.profiles.ValueProfile; -import com.oracle.truffle.api.source.SourceSection; -import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.data.RShareable; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage; import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; -@NodeChild(value = "n", type = RNode.class) -public abstract class GetNonSharedNode extends RNode implements RSyntaxNode { - // TODO This should not be an RSyntaxNode +public abstract class GetNonSharedNode extends Node { - private final ValueProfile shareableTypeProfile = ValueProfile.createClassProfile(); + public static final class GetNonSharedSyntaxNode extends RNode { - protected abstract RNode getN(); + @Child private RNode delegate; + @Child private GetNonSharedNode nonShared = GetNonSharedNodeGen.create(); - @Override - protected RSyntaxNode getRSyntaxNode() { - return getN().asRSyntaxNode(); - } + public GetNonSharedSyntaxNode(RNode delegate) { + this.delegate = delegate; + } - @Specialization - protected RTypedValue getNonShared(RShareable shareable) { - return shareableTypeProfile.profile(shareable).getNonShared(); - } + @Override + public Object execute(VirtualFrame frame) { + return nonShared.execute(delegate.execute(frame)); + } - protected static boolean isRShareable(Object o) { - return o instanceof RShareable; + @Override + protected RSyntaxNode getRSyntaxNode() { + return delegate.asRSyntaxNode(); + } } - @Specialization(guards = "!isRShareable(o)") - protected Object getNonShared(Object o) { - return o; - } + public abstract Object execute(Object value); - @Override - public void setSourceSection(SourceSection sourceSection) { - throw RInternalError.shouldNotReachHere(); + public static GetNonSharedNode create() { + return GetNonSharedNodeGen.create(); } - @Override - public SourceSection getLazySourceSection() { - return RSyntaxNode.INTERNAL; + @Specialization(guards = "shareable.getClass() == shareableClass") + protected RTypedValue getNonShared(RSharingAttributeStorage shareable, + @Cached("shareable.getClass()") Class<? extends RSharingAttributeStorage> shareableClass) { + return shareableClass.cast(shareable).getNonShared(); } - @Override - public SourceSection getSourceSection() { - return RSyntaxNode.INTERNAL; + @Fallback + protected Object getNonShared(Object o) { + RSharingAttributeStorage.verify(o); + return o; } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/IsFactorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/IsFactorNode.java index 7d3f63198c4c1d86195541aa9efcabfeb19f9231..2c8de03f940d0f2a7ce54b18f81daa16766e8b39 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/IsFactorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/IsFactorNode.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. */ @@ -39,7 +39,6 @@ public final class IsFactorNode extends UnaryNode { return inheritsCheck.execute(x); } - @Override public Object execute(Object value) { return executeIsFactor(value); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/NonNANode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/NonNANode.java index 397f7cb57b26d98c74ad59bb2d2d13b381fbe2c8..34332663004f748fa4a1f766c26fce3e7bc82ed0 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/NonNANode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/NonNANode.java @@ -24,7 +24,7 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; -import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.nodes.builtin.casts.MessageData; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RMissing; @@ -36,26 +36,22 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; public abstract class NonNANode extends CastNode { - private final RBaseNode callObj; - private final RError.Message message; - private final Object[] messageArgs; + private final MessageData message; private final Object naReplacement; private final BranchProfile warningProfile = BranchProfile.create(); - protected NonNANode(RBaseNode callObj, RError.Message message, Object[] messageArgs, Object naReplacement) { - this.callObj = callObj == null ? this : callObj; + protected NonNANode(MessageData message, Object naReplacement) { this.message = message; - this.messageArgs = messageArgs; this.naReplacement = naReplacement; + assert message != null || naReplacement != null; } protected NonNANode(Object naReplacement) { - this(null, null, null, naReplacement); + this(null, naReplacement); } public Object getNAReplacement() { @@ -66,12 +62,11 @@ public abstract class NonNANode extends CastNode { if (naReplacement != null) { if (message != null) { warningProfile.enter(); - handleArgumentWarning(arg, callObj, message, messageArgs); + handleArgumentWarning(arg, message); } return naReplacement; } else { - handleArgumentError(arg, callObj, message, messageArgs); - return null; + throw handleArgumentError(arg, message); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java index 03eda37330086b211fb655eaf8f39044fd8860df..52c861931e2d24a3b67b5c957da3e29cda2bd900 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java @@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RComplex; @@ -35,6 +36,7 @@ import com.oracle.truffle.r.runtime.data.RExpression; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RIntSequence; import com.oracle.truffle.r.runtime.data.RIntVector; +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.RLogicalVector; @@ -205,9 +207,23 @@ public abstract class PrecedenceNode extends RBaseNode { return LIST_PRECEDENCE; } + @Specialization + protected int doRInterop(RInteropScalar ri, boolean recursive) { + return LIST_PRECEDENCE; + } + + @Specialization(guards = {"isForeignObject(to)"}) + protected int doForeignObject(TruffleObject to, boolean recursive) { + return LIST_PRECEDENCE; + } + @Specialization(guards = {"!recursive", "args.getLength() == 1"}) protected int doArgsValuesAndNames(RArgsValuesAndNames args, boolean recursive, @Cached("createRecursive()") PrecedenceNode precedenceNode) { return precedenceNode.executeInteger(args.getArgument(0), recursive); } + + protected boolean isForeignObject(TruffleObject to) { + return RRuntime.isForeignObject(to); + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java index f6c14178278012d0d955b85109470e9667a1a166..ba6bf5714fabbcb7f76cb23751ebbd3ccd328cf7 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.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 @@ -24,15 +24,21 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; +import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RRaw; +import com.oracle.truffle.r.runtime.data.RS4Object; +import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.RTypes; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; @@ -73,7 +79,7 @@ public abstract class ToStringNode extends RBaseNode { return value; } if (quotes) { - return RRuntime.quoteString(value, false); + return RRuntime.escapeString(value, false, true); } return value; @@ -133,6 +139,19 @@ public abstract class ToStringNode extends RBaseNode { return RRuntime.logicalToString(operand); } + @Specialization + protected String toString(RS4Object obj, @SuppressWarnings("unused") boolean quotes, String separator, + @Cached(value = "createWithImplicit()") ClassHierarchyNode hierarchy) { + RStringVector classHierarchy = hierarchy.execute(obj); + Object clazz; + if (classHierarchy.getLength() > 0) { + clazz = toString(classHierarchy.getDataAt(0), true, separator); + } else { + throw RInternalError.shouldNotReachHere("S4 object has no class"); + } + return Utils.stringFormat("<S4 object of class %s>", clazz); + } + @FunctionalInterface private interface ElementFunction { String apply(int index, boolean quotes, String separator); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java index 358b1b3ce467b0eea5a5d1087d1f007dfc0fbdad..1df443ba8c97ea0df8b9b11c2f42a9540d0b1608 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java @@ -25,6 +25,8 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RTypedValue; @@ -33,7 +35,6 @@ public abstract class TypeofNode extends UnaryNode { protected static final int NUMBER_OF_CACHED_CLASSES = 5; - @Override public abstract RType execute(Object x); @Specialization @@ -80,4 +81,22 @@ public abstract class TypeofNode extends UnaryNode { protected static RType doGenericTyped(RTypedValue operand) { return operand.getRType(); } + + @Specialization(guards = "isForeignObject(object)") + protected RType doTruffleObject(@SuppressWarnings("unused") TruffleObject object) { + return RType.TruffleObject; + } + + protected static boolean isForeignObject(Object obj) { + return RRuntime.isForeignObject(obj); + } + + public static RType getTypeof(Object operand) { + CompilerAsserts.neverPartOfCompilation(); + return ((RTypedValue) RRuntime.asAbstractVector(operand)).getRType(); + } + + public static TypeofNode create() { + return TypeofNodeGen.create(); + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticBuiltinNode.java index 30a73667726f4ce93ffccb7cce8b61ae19bdf4ee..b251f47a8409c50103beae9c99b8ebc40e918665 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticBuiltinNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticBuiltinNode.java @@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.ops.UnaryArithmetic; import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory; -public abstract class UnaryArithmeticBuiltinNode extends RBuiltinNode implements UnaryArithmeticFactory { +public abstract class UnaryArithmeticBuiltinNode extends RBuiltinNode.Arg1 implements UnaryArithmeticFactory { @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create(); @Child private UnaryArithmeticNode unaryNode; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java index bd584cf1bdc35a4d19f814e6aa219aa6b2d3bb1c..2e4061d8fe6cf3a61dcbd7d29f35a37d41ecded6 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java @@ -22,14 +22,15 @@ */ package com.oracle.truffle.r.nodes.unary; +import com.oracle.truffle.api.CompilerDirectives; 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.r.nodes.primitive.UnaryMapNode; import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode; -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.RType; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; @@ -43,7 +44,7 @@ public abstract class UnaryArithmeticNode extends UnaryNode { protected final UnaryArithmeticFactory unary; private final Message error; - private final Object errorArgs; + private final Object[] errorArgs; protected final RType minPrecedence; public UnaryArithmeticNode(UnaryArithmeticFactory factory, RType minPrecedence, Message error, Object... errorArgs) { @@ -64,6 +65,8 @@ public abstract class UnaryArithmeticNode extends UnaryNode { this(factory, error, RType.Integer); } + public abstract Object execute(Object value); + @Specialization(guards = {"cachedNode != null", "cachedNode.isSupported(operand)"}) protected Object doCached(Object operand, @Cached("createCachedFast(operand)") UnaryMapNode cachedNode) { @@ -105,10 +108,17 @@ public abstract class UnaryArithmeticNode extends UnaryNode { @Fallback protected Object invalidArgType(@SuppressWarnings("unused") Object operand) { - if (errorArgs == null) { - throw RError.error(this, error); + CompilerDirectives.transferToInterpreter(); + if (errorArgs == null || errorArgs.length == 0) { + throw error(error); + } else if (errorArgs.length == 1) { + throw error(error, errorArgs[0]); + } else if (errorArgs.length == 2) { + throw error(error, errorArgs[0], errorArgs[1]); + } else if (errorArgs.length == 3) { + throw error(error, errorArgs[0], errorArgs[1], errorArgs[2]); } else { - throw RError.error(this, error, (Object[]) errorArgs); + throw RInternalError.shouldNotReachHere("too many error arguments in UnaryArithmeticNode"); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java index 2d3092d235814b373c0e89b9d5e45d89692e778a..5b66205f4b5eba5ae1d23b4bdbe465f8452f383c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java @@ -26,7 +26,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.TypeSystemReference; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; @@ -61,17 +60,13 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode { public abstract Object executeReduce(Object value, boolean naRm, boolean finite); @Child private MultiElemStringHandlerNode stringHandler; - - private final BinaryArithmeticFactory factory; - @Child private BinaryArithmetic arithmetic; + private final BinaryArithmeticFactory factory; protected final ReduceSemantics semantics; private final NACheck na = NACheck.create(); - private final ConditionProfile naRmProfile = ConditionProfile.createBinaryProfile(); - private final BranchProfile warningProfile = BranchProfile.create(); protected UnaryArithmeticReduceNode(ReduceSemantics semantics, BinaryArithmeticFactory factory) { this.factory = factory; @@ -89,15 +84,13 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode { private void emptyWarning() { if (semantics.getEmptyWarning() != null) { - warningProfile.enter(); - RError.warning(this, semantics.emptyWarning); + warning(semantics.emptyWarning); } } private void naResultWarning() { if (semantics.getNAResultWarning() != null) { - warningProfile.enter(); - RError.warning(this, semantics.getNAResultWarning()); + warning(semantics.getNAResultWarning()); } } @@ -177,11 +170,10 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode { return operand; } } else { - return na.check(operand) ? RRuntime.createComplexNA() : operand; + return na.check(operand) ? RComplex.createNA() : operand; } } else { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "complex"); + throw error(RError.Message.INVALID_TYPE_ARGUMENT, "complex"); } } @@ -202,16 +194,14 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode { return na.check(operand) ? RRuntime.STRING_NA : operand; } } else { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "character"); + throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character"); } } @SuppressWarnings("unused") @Specialization protected RRaw doString(RRaw operand, boolean naRm, boolean finite) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "raw"); + throw error(RError.Message.INVALID_TYPE_ARGUMENT, "raw"); } @Specialization @@ -360,7 +350,7 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode { if (profiledNaRm) { continue; } else { - return RRuntime.createComplexNA(); + return RComplex.createNA(); } } else { result = arithmetic.op(result.getRealPart(), result.getImaginaryPart(), current.getRealPart(), current.getImaginaryPart()); @@ -372,8 +362,7 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode { } return result; } else { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "complex"); + throw error(RError.Message.INVALID_TYPE_ARGUMENT, "complex"); } } @@ -390,8 +379,7 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode { } return semantics.getStringStart(); } else { - CompilerDirectives.transferToInterpreter(); - throw RError.error(invokingNode, RError.Message.INVALID_TYPE_ARGUMENT, "character"); + throw invokingNode.error(RError.Message.INVALID_TYPE_ARGUMENT, "character"); } } @@ -413,8 +401,7 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode { } return result; } else { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "character"); + throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character"); } } @@ -423,16 +410,14 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode { if (semantics.supportString) { return handleString(operand, naRm, finite, 0); } else { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "character"); + throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character"); } } @SuppressWarnings("unused") @Specialization protected RRaw doString(RRawVector operand, boolean naRm, boolean finite) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "raw"); + throw error(RError.Message.INVALID_TYPE_ARGUMENT, "raw"); } public static final class ReduceSemantics { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNode.java index 7101b814147b8a22fcb55f63582d8db38cc185ce..534423533dd52e74c8d5bf257e1917eb261dffe6 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNode.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 @@ -29,5 +29,4 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; @TypeSystemReference(RTypes.class) public abstract class UnaryNode extends RBaseNode { - public abstract Object execute(Object value); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java index 1d28787a2641fea4c12d0c5b7e20bda88bb6698a..29484784d21defcb7b3e791c940e8b4c77ca75ad 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java @@ -49,7 +49,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; import com.oracle.truffle.r.runtime.ops.na.NAProfile; @RBuiltin(name = "!", kind = PRIMITIVE, parameterNames = {""}, dispatch = OPS_GROUP_GENERIC, behavior = PURE) -public abstract class UnaryNotNode extends RBuiltinNode { +public abstract class UnaryNotNode extends RBuiltinNode.Arg1 { private final NACheck na = NACheck.create(); private final NAProfile naProfile = NAProfile.create(); @@ -209,6 +209,6 @@ public abstract class UnaryNotNode extends RBuiltinNode { @Fallback protected Object invalidArgType(@SuppressWarnings("unused") Object operand) { - throw RError.error(this, RError.Message.INVALID_ARG_TYPE); + throw error(RError.Message.INVALID_ARG_TYPE); } } diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/DefaultRParserFactory.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/DefaultRParserFactory.java index 38f9cdc524a0b9f5edf2b7d81e6dba286ce9eb1e..a058b86051debe14e79acfd5306b94d49ad5916b 100644 --- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/DefaultRParserFactory.java +++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/DefaultRParserFactory.java @@ -90,7 +90,7 @@ public class DefaultRParserFactory extends RParserFactory { String line = e.line <= source.getLineCount() ? source.getCode(e.line) : ""; String substring = line.substring(0, Math.min(line.length(), e.charPositionInLine + 1)); String token = e.token == null ? (substring.length() == 0 ? "" : substring.substring(substring.length() - 1)) : e.token.getText(); - if (e.token != null && e.token.getType() == Token.EOF && (e instanceof NoViableAltException || e instanceof MismatchedTokenException)) { + if (e.getUnexpectedType() == Token.EOF && (e instanceof NoViableAltException || e instanceof MismatchedTokenException)) { // the parser got stuck at the eof, request another line throw new IncompleteSourceException(e, source, token, substring, e.line); } else { diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java index 4b3743e6598b9a5e6f38c20f7d4206c28af54290..76e8351cb9a82020724fb76869eac71177c84b17 100644 --- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java +++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java @@ -88,6 +88,7 @@ public class ParserGeneration { "support ? for help", "support for hex float literals", "support for hex float literals without decimal point: 0x0p0", - "different warning for hex and dec integer literals" + "different warning for hex and dec integer literals", + "raise ZERO_LENGTH_VARIABLE errors in parser" }; } diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g index 317c4174ab4a4bdff5c3eaecf5c9a4b368b77e7c..3eb64bd8c0ee37a980a2f881ead4ce5d078f731e 100644 --- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g +++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g @@ -48,6 +48,8 @@ import com.oracle.truffle.r.runtime.nodes.RCodeBuilder.Argument; @lexer::header { //@formatter:off package com.oracle.truffle.r.parser; + +import com.oracle.truffle.r.runtime.RError; } @rulecatch { @@ -81,9 +83,19 @@ package com.oracle.truffle.r.parser; * Helper function to create a function lookup for the symbol in a given token. */ private T operator(Token op) { - return builder.lookup(src(op), op.getText(), true); + return builder.lookup(src(op), argName(op.getText()), true); } + /** + * Helper to check for empty lookups. + */ + private String argName(String name) { + if (name.length() == 0) { + throw RError.error(RError.NO_CALLER, RError.Message.ZERO_LENGTH_VARIABLE); + } + return name; + } + /** * Create a {@link SourceSection} from a single token. */ @@ -499,8 +511,8 @@ args [T firstArg] returns [List<Argument<T>> v] arg_expr [List<Argument<T>> l] @init { Token start = input.LT(1); } : e=expr { $l.add(RCodeBuilder.argument(src(start, last()), (String) null, $e.v)); } - | name=(ID | VARIADIC | NULL | STRING) n_ ASSIGN n_ e=expr { $l.add(RCodeBuilder.argument(src($name, last()), $name.text, $e.v)); } - | name=(ID | VARIADIC | NULL | STRING) n_ a=ASSIGN { $l.add(RCodeBuilder.argument(src($name, $a), $name.text, null)); } + | name=(ID | VARIADIC | NULL | STRING) n_ ASSIGN n_ e=expr { $l.add(RCodeBuilder.argument(src($name, last()), argName($name.text), $e.v)); } + | name=(ID | VARIADIC | NULL | STRING) n_ a=ASSIGN { $l.add(RCodeBuilder.argument(src($name, $a), argName($name.text), null)); } ; /// @@ -626,7 +638,12 @@ fragment BACKTICK_NAME | i = ~( '\\' | '`' ) { buf.appendCodePoint(i); } )* '`' - { setText(buf.toString()); } + { + if (buf.length() == 0) { + throw RError.error(RError.NO_CALLER, RError.Message.ZERO_LENGTH_VARIABLE); + } + setText(buf.toString()); + } ) ; diff --git a/com.oracle.truffle.r.pkgs/graalvm/DESCRIPTION b/com.oracle.truffle.r.pkgs/graalvm/DESCRIPTION new file mode 100644 index 0000000000000000000000000000000000000000..895818a9a3229e5f0ada80f3385e70e6fc44d91d --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/DESCRIPTION @@ -0,0 +1,12 @@ +Package: graalvm +Type: Package +Title: GraalVM integration with GNUR +Version: 1.0 +Date: 2017-04-06 +Author: Zbynek Slajchrt +Maintainer: Zbynek Slajchrt <zbynek.slajchrt@oracle.com> +Copyright: Oracle +Description: It demonstrates FastR performance and polyglot capabilities of GraalVM to GNUR users. +License: GPL-2 +Depends: curl, jsonlite +RoxygenNote: 6.0.1 diff --git a/com.oracle.truffle.r.pkgs/graalvm/NAMESPACE b/com.oracle.truffle.r.pkgs/graalvm/NAMESPACE new file mode 100644 index 0000000000000000000000000000000000000000..ce77a622a17c051ab5db2fc4bf8b50183bda16e3 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/NAMESPACE @@ -0,0 +1,17 @@ +# Generated by roxygen2: do not edit by hand + +export(g) +export(g.js) +export(g.r) +export(g.rb) +export(gget) +export(gget.js) +export(gget.r) +export(gget.rb) +export(graalvm.setup) +export(graalvm.start) +export(graalvm.stop) +export(gset) +export(gset.js) +export(gset.r) +export(gset.rb) diff --git a/com.oracle.truffle.r.pkgs/graalvm/R/g.R b/com.oracle.truffle.r.pkgs/graalvm/R/g.R new file mode 100644 index 0000000000000000000000000000000000000000..11190d265a2eae66b34b16136912e434a2645e2c --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/R/g.R @@ -0,0 +1,337 @@ +## + # 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. +## + +graalvmEnv <- new.env(parent = emptyenv()) +graalvmEnv$status <- FALSE + +graalvm.status <- function() { + graalvmEnv$status +} + +#' Set up the GraalVM agent +#' +#' @param home The home folder of the GraalVM installation +#' @param host The local host name at which the GraalVM agent is listening +#' @param port The port at which the GraalVM agent is listening +#' @param rlibs The value of the FastR R_LIBS environmental variable. The default +#' value is calculated as paste0(graalvm.home, "/language/R/library"). +#' @examples +#' graalvm.setup("~/work/graalvm-0.21") +#' @export +graalvm.setup <- function(home, host = "localhost", port = 9876, rlibs = paste0(home, "/language/R/library")) { + options(graalvm.home = home, graalvm.host = host, graalvm.port = port, graalvm.rlibs = rlibs) +} + +commandURL <- function(cmd) { + gHost <- getOption("graalvm.host"); + gPort <- getOption("graalvm.port"); + sprintf("http://%s:%d/%s", gHost, gPort, cmd) +} + +ping <- function() { + pingURL <- commandURL("ping") + tryCatch({ suppressWarnings(readLines(pingURL, warn=FALSE)); TRUE }, error = function(e) FALSE) +} + +#' Start the GraalVM agent. The agent is normally started automatically upon the first +#' code ecxecution. +#' @export +graalvm.start <- function() { + if (!ping()) { + graalvmEnv$status <- FALSE + gHome <- getOption("graalvm.home"); + if (is.null(gHome)) stop("No GraalVM home configured. Use graalvm.setup() to specify it.") + + serverScriptPath <- attr(packageDescription("graalvm"), "file") + serverScriptPath <- substr(serverScriptPath, 1, nchar(serverScriptPath)-16) + serverScriptPath <- paste0(serverScriptPath, "data/server.js") + + libEnvVar <- paste0("R_LIBS=", getOption("graalvm.rlibs")) + + gHost <- getOption("graalvm.host"); + gPort <- getOption("graalvm.port"); + + nodeLaunchCmd <- paste0(libEnvVar, " ", gHome, "/bin/node ", serverScriptPath, " ", gHost, " ", gPort, " &") + system(nodeLaunchCmd, ignore.stdout = TRUE, ignore.stderr = TRUE) + + attempts <- 0L + while(!ping()) { + Sys.sleep(1) + attempts <- attempts + 1L + if (attempts >= 30) stop("Cannot launch GraalVM agent") + } + + graalvmEnv$status <- TRUE + } + + # register the function stopping the agent on exit + prevLast <- NULL + if (exists(".Last")) { + prevLast <- .Last + } + .Last <<- function() { + tryCatch(graalvm::graalvm.stop(), error = function(e) print(e)) + # invoke the previous callback if any + if (!is.null(prevLast)) prevLast() + } + TRUE +} + +#' Stop the GraalVM agent. +#' @export +graalvm.stop <- function() { + tryCatch({ + suppressWarnings(readLines(commandURL("stop"), warn=FALSE)) + graalvmEnv$status <- FALSE + TRUE + }, error = function(e) FALSE) +} + +#' Execute code by GraalVM using the language interpreter that corresponds +#' to the language mimetype. +#' +#' @param code the code to be executed. It must be a language element as long as the target +#' language is R, otherwise it must be a string. +#' @param echo controls whether this function returns the result of the interpreted code. +#' The default value is TRUE. +#' @param mimetype The mimetype of the target language. Currently supported values are +#' "application/x-r", "text/javascript" and "application/x-ruby". +#' @family execution functions +#' @examples +#' g(runif(10^3)) +#' g(runif(10^8), echo = FALSE) # We do not want that the result is returned due to its size +#' g("1 < 2", mimetype = "text/javascript") +#' @export +g <- function(code, echo = TRUE, mimetype = "application/x-r") { + if (mimetype == "application/x-r") { + code <- deparse(substitute(code)) + } else { + if (!is.character(code)) stop("The code argument must a character vector") + } + send(code, echo, mimetype) +} + +#' Execute R code. +#' @examples +#' g.r("runif(10^3)") +#' @family execution functions +#' @export +g.r <- function(code, echo = TRUE) { + if (!is.character(code)) stop("The code argument must a character vector") + send(code, echo, "application/x-r") +} + +#' Execute JavaScript code. +#' @examples +#' g.js("1 < 2") +#' @family execution functions +#' @export +g.js <- function(code, echo = TRUE) { + if (!is.character(code)) stop("The code argument must a character vector") + send(code, echo, "text/javascript") +} + +#' Execute Ruby code. +#' @examples +#' g.rb("1 < 2") +#' @family execution functions +#' @export +g.rb <- function(code, echo = TRUE) { + if (!is.character(code)) stop("The code argument must a character vector") + send(code, echo, "application/x-ruby") +} + +#' Assign a value to a paired variable. The value is assigned both locally and remotely. +#' The local variable must have been initialized by one of the language specific gget.* or +#' ggset.* functions. +#' +#' @family paired variables +#' @examples +#' # Create and initialize a variable in JS +#' g.js("a = 1") +#' # Pick up the a variable from JS and define its counterpart in GNUR +#' gget.js(a) +#' a +#' # Increment the variable both locally and in JS +#' gset(a, a + 1) +#' a +#' g.js("a[0]") +#' g.js("a[1] = 10") +#' gget(a) +#' a +#' @export +gset <- function(var, value = var) { + varName <- deparse(substitute(var)) + if (exists(varName)) { + meta <- attr(var, "graalvm") + if (is.null(meta)) { + stop(paste("Unpaired variable ", varName)) + } + deparsedValue = NULL + if (meta$mimetype == "application/x-r") { + deparsedValue <- paste(deparse(substitute(value)), collapse="\n") + } + setVar(varName, value, deparsedValue, meta$mimetype) + } else { + stop(paste("Undefined variable ", varName)) + } +} + +#' Assign the value to the paired variable in Graal FastR and locally. +#' +#' @family paired variables +#' @export +gset.r <- function(var, value) setVar(deparse(substitute(var)), value, paste(deparse(substitute(value)), collapse="\n"), "application/x-r") + +#' Assign the value to the paired variable in Graal JS and locally. +#' +#' @family paired variables +#' @export +gset.js <- function(var, value) setVar(deparse(substitute(var)), value, NULL, "text/javascript") + +#' Assign the value to the paired variable in Graal Ruby and locally. +#' +#' @family paired variables +#' @export +gset.rb <- function(var, value) setVar(deparse(substitute(var)), value, NULL, "application/x-ruby") + +#' Retrieve the variable defined in a GraalVM language. The local variable must have been +#' initialized by one of the language specific gget.* or ggset.* functions. +#' +#' @family paired variables +#' @export +gget <- function(var) { + varName <- deparse(substitute(var)) + if (exists(varName)) { + meta <- attr(var, "graalvm") + if (is.null(meta)) { + stop(paste("Unpaired variable ", varName)) + } + getVar(varName, meta$mimetype) + } else { + stop(paste("Undefined variable ", varName)) + } +} + +#' Retrieve the variable defined in GraalVM FastR. +#' +#' @family paired variables +#' @export +gget.r <- function(var) getVar(deparse(substitute(var)), "application/x-r") + +#' Retrieve the variable defined in GraalVM JS. +#' +#' @family paired variables +#' @export +gget.js <- function(var) getVar(deparse(substitute(var)), "text/javascript") + +#' Retrieve the variable defined in GraalVM Ruby. +#' +#' @family paired variables +#' @export +gget.rb <- function(var) getVar(deparse(substitute(var)), "application/x-ruby") + +setVar <- function(varName, value, deparsedValue, mimetype="application/x-r") { + localValue <- value + meta <- NULL + if (exists(varName)) { + meta <- attr(var, "graalvm") + } + if (is.null(meta)) { + meta <- list(varName = varName, mimetype = mimetype) + attr(localValue, "graalvm") <- meta + } + if (meta$mimetype == "application/x-r") { + code <- paste0(meta$varName, "<-", deparsedValue) + } else if (meta$mimetype == "text/javascript") { + code <- paste0(meta$varName, "=", toJSON(value)) + } else if (meta$mimetype == "application/x-ruby") { + code <- paste0("$", meta$varName, "=", toJSON(value)) + } else { + stop(paste("Unsupported language mimetype:", mimetype)) + } + send(code, FALSE, meta$mimetype) + + assign(varName, localValue, inherits = TRUE) +} + +getVar <- function(varName, mimetype="application/x-r") { + meta <- NULL + if (exists(varName)) { + meta <- attr(var, "graalvm") + } + if (is.null(meta)) { + meta <- list(varName = varName, mimetype = mimetype) + } + if (meta$mimetype == "application/x-r") { + code <- meta$varName + } else if (meta$mimetype == "text/javascript") { + code <- meta$varName + } else if (meta$mimetype == "application/x-ruby") { + code <- paste0("$", meta$varName) + } else { + stop(paste("Unsupported language mimetype:", mimetype)) + } + value <- send(code, TRUE, meta$mimetype) + + if (!is.null(value)) { + meta <- list("varName" = varName, "mimetype" = mimetype) + attr(value, "graalvm") <- meta + } + + assign(varName, value, inherits = TRUE) +} + +send <- function(code, echo, mimetype) { + tryCatch(sendAttempt(code, echo, mimetype), error = function(e) { + # try to restart the agent and invoke it agains + graalvm.start() + sendAttempt(code, echo, mimetype) + }) +} + +sendAttempt <- function(code, echo, mimetype) { + code <- paste(code, collapse="\n") + if (!graalvmEnv$status) { + graalvm.start() + } + h <- new_handle(failonerror = FALSE) + handle_setform(h, code=code, echo=as.character(echo), mimetype=mimetype) + url <- commandURL("") + resp <- curl_fetch_memory(url, handle = h) + respData <- rawToChar(resp$content) + respData <- strsplit(respData, "\r\n")[[1]] + if (mimetype == "application/x-r") { + respObj <- eval(parse(text=respData)) + } else if (mimetype == "text/javascript") { + respObj <- fromJSON(respData) + } else if (mimetype == "application/x-ruby") { + respObj <- fromJSON(respData) + } + + if (resp$status_code >= 400) { + stop(respObj) + } else { + respObj + } +} diff --git a/com.oracle.truffle.r.pkgs/graalvm/R/graalvm.R b/com.oracle.truffle.r.pkgs/graalvm/R/graalvm.R new file mode 100644 index 0000000000000000000000000000000000000000..2c6c4b66e7195f7e6c09c8bb991b06269e8a5044 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/R/graalvm.R @@ -0,0 +1,53 @@ +#' GraalVM R package is supposed to demonstrate FastR performance and polyglot capabilities +#' of GraalVM to GNUR users. +#' +#' @name graalvm +#' @examples +#' # Loading and setting up +#' +#' library(graalvm) +#' graalvm.setup("~/work/graalvm-0.21") +#' +#' # Code execution +#' g(v <- runif(1e8)) +#' g(f <- function(x) { s <- 0; for (i in seq_along(x)) s <- s + x[[i]]; s }) +#' g(system.time(f(v))) +#' g(system.time(f(v))) +#' +#' g.js("1 < 2") +#' g.rb("$a = 2") +#' +#' +#' # Paired variables +#' +#' # Create and initialize paired variables: +#' gset.r(a1, TRUE) +#' gset.js(a2, c(1,2)) +#' gset.rb(a3, list(a=1,b="2")) +#' a1 +#' a2 +#' a3 +#' g.r("a1") +#' g.js("a2") +#' g.rb("$a3") +#' +#' g(a1 <- FALSE) +#' gget(a1) +#' a1 +#' +#' # Paired functions +#' +#' # Create a paired function +#' gset.r(measure, function(n) { system.time(runif(n)) }) +#' # Execute the local version of the paired function +#' measure(1e8) +#' # Execute the remote version of the paired function +#' g(measure(1e8)) +#' +#' # Executing a script file +#' +#' tmp <- tempfile() +#' writeLines(con = tmp, c("x<-10", "y<-x^2", "y")) +#' g.r(readLines(con=tmp)) +#' +NULL diff --git a/com.oracle.truffle.r.pkgs/graalvm/data/handler.fr b/com.oracle.truffle.r.pkgs/graalvm/data/handler.fr new file mode 100644 index 0000000000000000000000000000000000000000..d45d981de98a86d042f881a5e5d44ca06a9572e2 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/data/handler.fr @@ -0,0 +1,44 @@ +## + # 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. +## + +inp <- NULL +out <- NULL +err <- FALSE + +parser <- function(expr) { + # The expression is temporarily put into the block due to a bug in the FastR that is + # bundled into GraalVM 0.21, which causes that the expression eval(parse(text="x")) fails. + # The bug is already fixed in the newest version of FastR. + exp <<- parse(text = paste0("{", expr, "}")) +} + +deparseObject <- function(obj) paste(deparse(obj), collapse = "\r\n") + +result <- function() deparseObject(out) + +isError <- function() err + +.fastr.interop.export('parser', parser) +.fastr.interop.export('deparseObject', deparseObject) +.fastr.interop.export('result', result) +.fastr.interop.export('isError', isError) diff --git a/com.oracle.truffle.r.pkgs/graalvm/data/handler.rb b/com.oracle.truffle.r.pkgs/graalvm/data/handler.rb new file mode 100644 index 0000000000000000000000000000000000000000..4189fed1626f53334576d32e2feaf7d55d5af30b --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/data/handler.rb @@ -0,0 +1,37 @@ +=begin + 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. +=end + +require 'json' + +$expr = "" + +def storeExpr(e) + $expr = Truffle::Interop.from_java_string(e) +end + +def toJSON(res) + Truffle::Interop.to_java_string(res.to_json) +end + +Truffle::Interop.export('storeExpr', method(:storeExpr)) +Truffle::Interop.export('rubyToJSON', method(:toJSON)) \ No newline at end of file diff --git a/com.oracle.truffle.r.pkgs/graalvm/data/server.js b/com.oracle.truffle.r.pkgs/graalvm/data/server.js new file mode 100644 index 0000000000000000000000000000000000000000..0e3604a98a1bb9be7897c69ef71b6e478c387edf --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/data/server.js @@ -0,0 +1,196 @@ +/* + * 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 + * 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. + */ + +var fs = require('fs'); +var http = require("http"); + +function parseParams(body) { + var lines = body.split('\r\n'); + var paramName = null; + var paramValue = ""; + var params = {}; + for(var i = 0; i < lines.length; i++) { + if (lines[i].startsWith("--------------------------")) { + if (paramName != null) { + params[paramName] = paramValue; + paramName = null; + paramValue = ""; + } + continue; + } + if (lines[i].startsWith("Content-Disposition:")) { + paramName = lines[i].split('=')[1]; + paramName = paramName.substring(1, paramName.length - 1); + i++; + continue; + } + if (lines[i] === "") { + continue; + } + paramValue += lines[i]; + } + + return params; +} + +function evalJS(code, echo) { + //console.log("Executing JS code: '" + code + "'"); + var res = {}; + try { + r = eval(code) + res.isError = false; + if (echo) { + res.data = JSON.stringify(r); + } else { + res.data = JSON.stringify(null); + } + } catch (error) { + //console.log("Caught error:" + JSON.stringify(error)); + res.isError = true; + res.data = "" + error; + } + return res; +} + +var rHandlerScript = fs.readFileSync( __dirname + "/handler.fr", "utf8"); +Interop.eval("application/x-r", rHandlerScript); + +rParser = Interop.import('parser'); +rResult = Interop.import('result'); +rIsError = Interop.import('isError'); +deparseObject = Interop.import('deparseObject'); + +function evalR(code, echo) { + rParser(code); + if (echo) { + Interop.eval("application/x-r", "err <- TRUE; out <- tryCatch({ err <- TRUE; r <- eval(exp); err <- FALSE; r }, error = function(e) e$message)"); + } else { + Interop.eval("application/x-r", "err <- TRUE; out <- tryCatch({ err <- TRUE; eval(exp); err <- FALSE; NULL }, error = function(e) e$message)"); + } + var res = {} + res.data = rResult(); + res.isError = rIsError(); + return res; +} + +var rubyHandlerScript = fs.readFileSync( __dirname + "/handler.rb", "utf8"); +Interop.eval("application/x-ruby", rubyHandlerScript); +rubyStoreExpr = Interop.import('storeExpr'); +rubyToJSON = Interop.import('rubyToJSON'); + +function evalRuby(code, echo) { + rubyStoreExpr(code); + var r; + code = `begin + eval($expr) + rescue Exception => exc + -1 + end`; + if (echo) { + r = Interop.eval("application/x-ruby", code); + } else { + r = Interop.eval("application/x-ruby", code); + } + var res = {} + rJSON = rubyToJSON(r); + //console.log("Result from Ruby:" + rJSON); + res.data = rJSON; + res.isError = false; + return res; +} + +function processPost(request, response) { + var queryData = ""; + + if(request.method == 'POST') { + request.on('data', function(data) { + queryData += data; + if(queryData.length > 1e6) { + queryData = ""; + response.writeHead(413, {'Content-Type': 'text/plain'}).end(); + request.connection.destroy(); + } + }); + + request.on('end', function() { + var params = parseParams(queryData); + //console.log("Params: " + JSON.stringify(params)); + var echo = params.echo === "TRUE"; + var res; + if (params.mimetype == "application/x-r") { + res = evalR(params.code, echo); + } else if (params.mimetype == "text/javascript") { + res = evalJS(params.code, echo); + } else if (params.mimetype == "application/x-ruby") { + res = evalRuby(params.code, echo); + } else { + res = { + isError : true, + data : deparseObject("Unsupported language: " + params.mimetype) + } + } + if (res.isError) { + response.writeHead(400, {'Content-Type': 'text/plain'}); + } else { + response.writeHead(200, "OK", {'Content-Type': 'text/plain'}); + } + response.end(res.data); + + }); + + } else { + response.writeHead(405, {'Content-Type': 'text/plain'}); + response.end(); + } +} + +// Launch the server +console.log("Starting GraalVM agent..."); + +var server = http.createServer(function (inp, out) { + var command = inp.url.substring(1); + if (command == "ping") { + out.end("pong"); + } else if (command == "stop") { + console.log("GraalVM agent stopped"); + out.end(command, null, function() { + process.exit(0); + }); + } else { + if(inp.method == 'POST') { + processPost(inp, out); + } else { + out.writeHead(200, "OK", {'Content-Type': 'text/plain'}); + out.end(); + } + } +}); + +host = process.argv[2] +port = parseInt(process.argv[3]) +server.listen(port, host); +server.on('error', function(err) { + console.log("Caught error: " + err); +}); + +console.log("GraalVM agent accepting at " + host + ":" + port); diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/g.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/g.Rd new file mode 100644 index 0000000000000000000000000000000000000000..3038fd1e7f7b3d6e5308f699507ee072159f9d1f --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/man/g.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/g.R +\name{g} +\alias{g} +\title{Execute code by GraalVM using the language interpreter that corresponds +to the language mimetype.} +\usage{ +g(code, echo = TRUE, mimetype = "application/x-r") +} +\arguments{ +\item{code}{the code to be executed. It must be a language element as long as the target +language is R, otherwise it must be a string.} + +\item{echo}{controls whether this function returns the result of the interpreted code. +The default value is TRUE.} + +\item{mimetype}{The mimetype of the target language. Currently supported values are +"application/x-r", "text/javascript" and "application/x-ruby".} +} +\description{ +Execute code by GraalVM using the language interpreter that corresponds +to the language mimetype. +} +\examples{ +g(runif(10^3)) +g(runif(10^8), echo = FALSE) # We do not want that the result is returned due to its size +g("1 < 2", mimetype = "text/javascript") +} +\seealso{ +Other execution functions: \code{\link{g.js}}, + \code{\link{g.rb}}, \code{\link{g.r}} +} diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/g.js.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/g.js.Rd new file mode 100644 index 0000000000000000000000000000000000000000..7d9287f25b71c1d809c72a0d6eb58f592681c666 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/man/g.js.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/g.R +\name{g.js} +\alias{g.js} +\title{Execute JavaScript code.} +\usage{ +g.js(code, echo = TRUE) +} +\description{ +Execute JavaScript code. +} +\examples{ +g.js("1 < 2") +} +\seealso{ +Other execution functions: \code{\link{g.rb}}, + \code{\link{g.r}}, \code{\link{g}} +} diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/g.r.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/g.r.Rd new file mode 100644 index 0000000000000000000000000000000000000000..3566a2a0b4fd3f87e577ab3ad4db38f90c0619bc --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/man/g.r.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/g.R +\name{g.r} +\alias{g.r} +\title{Execute R code.} +\usage{ +g.r(code, echo = TRUE) +} +\description{ +Execute R code. +} +\examples{ +g.r("runif(10^3)") +} +\seealso{ +Other execution functions: \code{\link{g.js}}, + \code{\link{g.rb}}, \code{\link{g}} +} diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/g.rb.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/g.rb.Rd new file mode 100644 index 0000000000000000000000000000000000000000..f307ee4a34fc0c8e756eaff1470f830392cea509 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/man/g.rb.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/g.R +\name{g.rb} +\alias{g.rb} +\title{Execute Ruby code.} +\usage{ +g.rb(code, echo = TRUE) +} +\description{ +Execute Ruby code. +} +\examples{ +g.rb("1 < 2") +} +\seealso{ +Other execution functions: \code{\link{g.js}}, + \code{\link{g.r}}, \code{\link{g}} +} diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/gget.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/gget.Rd new file mode 100644 index 0000000000000000000000000000000000000000..e0515efb005afd1492d454b56ee438b9e77508d8 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/man/gget.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/g.R +\name{gget} +\alias{gget} +\title{Retrieve the variable defined in a GraalVM language. The local variable must have been +initialized by one of the language specific gget.* or ggset.* functions.} +\usage{ +gget(var) +} +\description{ +Retrieve the variable defined in a GraalVM language. The local variable must have been +initialized by one of the language specific gget.* or ggset.* functions. +} +\seealso{ +Other paired variables: \code{\link{gget.js}}, + \code{\link{gget.rb}}, \code{\link{gget.r}}, + \code{\link{gset.js}}, \code{\link{gset.rb}}, + \code{\link{gset.r}}, \code{\link{gset}} +} diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/gget.js.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/gget.js.Rd new file mode 100644 index 0000000000000000000000000000000000000000..7caf44f206c6d7ab4de17c4b6d6859963e53807e --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/man/gget.js.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/g.R +\name{gget.js} +\alias{gget.js} +\title{Retrieve the variable defined in GraalVM JS.} +\usage{ +gget.js(var) +} +\description{ +Retrieve the variable defined in GraalVM JS. +} +\seealso{ +Other paired variables: \code{\link{gget.rb}}, + \code{\link{gget.r}}, \code{\link{gget}}, + \code{\link{gset.js}}, \code{\link{gset.rb}}, + \code{\link{gset.r}}, \code{\link{gset}} +} diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/gget.r.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/gget.r.Rd new file mode 100644 index 0000000000000000000000000000000000000000..df1678e584988b605466d858358539f9ce29b430 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/man/gget.r.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/g.R +\name{gget.r} +\alias{gget.r} +\title{Retrieve the variable defined in GraalVM FastR.} +\usage{ +gget.r(var) +} +\description{ +Retrieve the variable defined in GraalVM FastR. +} +\seealso{ +Other paired variables: \code{\link{gget.js}}, + \code{\link{gget.rb}}, \code{\link{gget}}, + \code{\link{gset.js}}, \code{\link{gset.rb}}, + \code{\link{gset.r}}, \code{\link{gset}} +} diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/gget.rb.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/gget.rb.Rd new file mode 100644 index 0000000000000000000000000000000000000000..4dfe3fd3fef1f8f1a228aa829e49fa4f16f92a27 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/man/gget.rb.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/g.R +\name{gget.rb} +\alias{gget.rb} +\title{Retrieve the variable defined in GraalVM Ruby.} +\usage{ +gget.rb(var) +} +\description{ +Retrieve the variable defined in GraalVM Ruby. +} +\seealso{ +Other paired variables: \code{\link{gget.js}}, + \code{\link{gget.r}}, \code{\link{gget}}, + \code{\link{gset.js}}, \code{\link{gset.rb}}, + \code{\link{gset.r}}, \code{\link{gset}} +} diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.Rd new file mode 100644 index 0000000000000000000000000000000000000000..a77541d69d508e1551913b79f81c471d5ad9db42 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.Rd @@ -0,0 +1,59 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/graalvm.R +\name{graalvm} +\alias{graalvm} +\title{GraalVM R package is supposed to demonstrate FastR performance and polyglot capabilities +of GraalVM to GNUR users.} +\description{ +GraalVM R package is supposed to demonstrate FastR performance and polyglot capabilities +of GraalVM to GNUR users. +} +\examples{ +# Loading and setting up + +library(graalvm) +graalvm.setup("~/work/graalvm-0.21") + +# Code execution +g(v <- runif(1e8)) +g(f <- function(x) { s <- 0; for (i in seq_along(x)) s <- s + x[[i]]; s }) +g(system.time(f(v))) +g(system.time(f(v))) + +g.js("1 < 2") +g.rb("$a = 2") + + +# Paired variables + +# Create and initialize paired variables: +gset.r(a1, TRUE) +gset.js(a2, c(1,2)) +gset.rb(a3, list(a=1,b="2")) +a1 +a2 +a3 +g.r("a1") +g.js("a2") +g.rb("$a3") + +g(a1 = FALSE) +gget(a1) +a1 + +# Paired functions + +# Create a paired function +gset.r(measure, function(n) { system.time(runif(n)) }) +# Execute the local version of the paired function +measure(1e8) +# Execute the remote version of the paired function +g(measure(1e8)) + +# Executing a script file + +tmp <- tempfile() +writeLines(con = tmp, c("x<-10", "y<-x^2", "y")) +g.r(readLines(con=tmp)) + +} diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.setup.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.setup.Rd new file mode 100644 index 0000000000000000000000000000000000000000..9007932d6d936816d018cd3c0e24b8e3ec171a76 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.setup.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/g.R +\name{graalvm.setup} +\alias{graalvm.setup} +\title{Set up the GraalVM agent} +\usage{ +graalvm.setup(home, host = "localhost", port = 9876, rlibs = paste0(home, + "/language/R/library")) +} +\arguments{ +\item{home}{The home folder of the GraalVM installation} + +\item{host}{The local host name at which the GraalVM agent is listening} + +\item{port}{The port at which the GraalVM agent is listening} + +\item{rlibs}{The value of the FastR R_LIBS environmental variable. The default +value is calculated as paste0(graalvm.home, "/language/R/library").} +} +\description{ +Set up the GraalVM agent +} +\examples{ +graalvm.setup("~/work/graalvm-0.21") +} diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.start.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.start.Rd new file mode 100644 index 0000000000000000000000000000000000000000..1527a6cf91f2bb39dc5edb722599aeea5ee0e4fc --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.start.Rd @@ -0,0 +1,13 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/g.R +\name{graalvm.start} +\alias{graalvm.start} +\title{Start the GraalVM agent. The agent is normally started automatically upon the first +code ecxecution.} +\usage{ +graalvm.start() +} +\description{ +Start the GraalVM agent. The agent is normally started automatically upon the first +code ecxecution. +} diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.stop.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.stop.Rd new file mode 100644 index 0000000000000000000000000000000000000000..d559fddba1591d5d1785d13337ddd8613533fc35 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.stop.Rd @@ -0,0 +1,11 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/g.R +\name{graalvm.stop} +\alias{graalvm.stop} +\title{Stop the GraalVM agent.} +\usage{ +graalvm.stop() +} +\description{ +Stop the GraalVM agent. +} diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/gset.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/gset.Rd new file mode 100644 index 0000000000000000000000000000000000000000..9c139e088c901d71ca9df399909e1c8aea79c40f --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/man/gset.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/g.R +\name{gset} +\alias{gset} +\title{Assign a value to a paired variable. The value is assigned both locally and remotely. +The local variable must have been initialized by one of the language specific gget.* or +ggset.* functions.} +\usage{ +gset(var, value = var) +} +\description{ +Assign a value to a paired variable. The value is assigned both locally and remotely. +The local variable must have been initialized by one of the language specific gget.* or +ggset.* functions. +} +\examples{ +# Create and initialize a variable in JS +g.js("a = 1") +# Pick up the a variable from JS and define its counterpart in GNUR +gget.js(a) +a +# Increment the variable both locally and in JS +gset(a, a + 1) +a +g.js("a[0]") +g.js("a[1] = 10") +gget(a) +a +} +\seealso{ +Other paired variables: \code{\link{gget.js}}, + \code{\link{gget.rb}}, \code{\link{gget.r}}, + \code{\link{gget}}, \code{\link{gset.js}}, + \code{\link{gset.rb}}, \code{\link{gset.r}} +} diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/gset.js.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/gset.js.Rd new file mode 100644 index 0000000000000000000000000000000000000000..1cf7308f64ce9e3c396f393bc8fb374087211073 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/man/gset.js.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/g.R +\name{gset.js} +\alias{gset.js} +\title{Assign the value to the paired variable in Graal JS and locally.} +\usage{ +gset.js(var, value) +} +\description{ +Assign the value to the paired variable in Graal JS and locally. +} +\seealso{ +Other paired variables: \code{\link{gget.js}}, + \code{\link{gget.rb}}, \code{\link{gget.r}}, + \code{\link{gget}}, \code{\link{gset.rb}}, + \code{\link{gset.r}}, \code{\link{gset}} +} diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/gset.r.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/gset.r.Rd new file mode 100644 index 0000000000000000000000000000000000000000..669c2c700cab73040056c02fec68c9a55d1773c0 --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/man/gset.r.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/g.R +\name{gset.r} +\alias{gset.r} +\title{Assign the value to the paired variable in Graal FastR and locally.} +\usage{ +gset.r(var, value) +} +\description{ +Assign the value to the paired variable in Graal FastR and locally. +} +\seealso{ +Other paired variables: \code{\link{gget.js}}, + \code{\link{gget.rb}}, \code{\link{gget.r}}, + \code{\link{gget}}, \code{\link{gset.js}}, + \code{\link{gset.rb}}, \code{\link{gset}} +} diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/gset.rb.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/gset.rb.Rd new file mode 100644 index 0000000000000000000000000000000000000000..45aaef4d8edb7caeb861c13c1c8501ab5ed9a05e --- /dev/null +++ b/com.oracle.truffle.r.pkgs/graalvm/man/gset.rb.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/g.R +\name{gset.rb} +\alias{gset.rb} +\title{Assign the value to the paired variable in Graal Ruby and locally.} +\usage{ +gset.rb(var, value) +} +\description{ +Assign the value to the paired variable in Graal Ruby and locally. +} +\seealso{ +Other paired variables: \code{\link{gget.js}}, + \code{\link{gget.rb}}, \code{\link{gget.r}}, + \code{\link{gget}}, \code{\link{gset.js}}, + \code{\link{gset.r}}, \code{\link{gset}} +} diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/LibPaths.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/LibPaths.java index 2292780c3fcd9ecd6392f10f1e06920e26b49723..86b8d0a62c33348b68b95270c11e0f69816917dd 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/LibPaths.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/LibPaths.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 @@ -25,6 +25,7 @@ package com.oracle.truffle.r.runtime.ffi; import java.nio.file.FileSystems; import java.nio.file.Path; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.REnvVars; import com.oracle.truffle.r.runtime.RPlatform; import com.oracle.truffle.r.runtime.RPlatform.OSInfo; @@ -34,6 +35,7 @@ public class LibPaths { /** * Returns the absolute path to the directory containing the builtin libraries. */ + @TruffleBoundary public static String getBuiltinLibPath() { return FileSystems.getDefault().getPath(REnvVars.rHome(), "lib").toString(); } @@ -42,6 +44,7 @@ public class LibPaths { * Returns the absolute path to the builtin library {@code libName} for use with * {@link System#load}. */ + @TruffleBoundary public static String getBuiltinLibPath(String libName) { String rHome = REnvVars.rHome(); OSInfo osInfo = RPlatform.getOSInfo(); @@ -53,6 +56,7 @@ public class LibPaths { * Returns the absolute path to the shared library associated with package {@code name}. (Does * not check for existence). */ + @TruffleBoundary public static String getPackageLibPath(String name) { String rHome = REnvVars.rHome(); String packageDir = "library"; diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Grid.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Grid.java deleted file mode 100644 index 8aad787c5526a3ef2f7f9b8bbb80790a34762857..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Grid.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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.runtime.ffi.generic; - -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.r.runtime.env.REnvironment; -import com.oracle.truffle.r.runtime.ffi.CallRFFI; -import com.oracle.truffle.r.runtime.ffi.DLL; -import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; -import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; -import com.oracle.truffle.r.runtime.ffi.GridRFFI; -import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; -import com.oracle.truffle.r.runtime.ffi.RFFIFactory; - -public class Generic_Grid implements GridRFFI { - private static final String GRID = "grid"; - - private static class Generic_InitGridNode extends InitGridNode { - private static final String L_InitGrid = "L_initGrid"; - @Child private CallRFFI.InvokeCallNode invokeCallNode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode(); - @Child DLL.RFindSymbolNode findSymbolNode = DLL.RFindSymbolNode.create(); - @CompilationFinal private NativeCallInfo initNativeCallInfo; - - @Override - public Object execute(REnvironment gridEvalEnv) { - if (initNativeCallInfo == null) { - initNativeCallInfo = createNativeCallInfo(L_InitGrid, findSymbolNode); - } - return invokeCallNode.execute(initNativeCallInfo, new Object[]{gridEvalEnv}); - } - } - - private static class Generic_KillGridNode extends KillGridNode { - private static final String L_KillGrid = "L_killGrid"; - @Child private CallRFFI.InvokeCallNode invokeCallNode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode(); - @Child DLL.RFindSymbolNode findSymbolNode = DLL.RFindSymbolNode.create(); - @CompilationFinal private NativeCallInfo killNativeCallInfo; - - @Override - public Object execute() { - if (killNativeCallInfo == null) { - killNativeCallInfo = createNativeCallInfo(L_KillGrid, findSymbolNode); - } - return invokeCallNode.execute(killNativeCallInfo, new Object[0]); - } - - } - - private static NativeCallInfo createNativeCallInfo(String call, DLL.RFindSymbolNode findSymbolNode) { - DLLInfo dllInfo = DLL.findLibrary(GRID); - assert dllInfo != null; - SymbolHandle symbolHandle = findSymbolNode.execute(call, GRID, DLL.RegisteredNativeSymbol.any()); - assert symbolHandle != DLL.SYMBOL_NOT_FOUND; - return new NativeCallInfo(call, symbolHandle, dllInfo); - } - - @Override - public InitGridNode createInitGridNode() { - return new Generic_InitGridNode(); - } - - @Override - public KillGridNode createKillGridNode() { - return new Generic_KillGridNode(); - } - -} diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java index 170f820fd28611c2b6d286f668ec8320198a6862..06d6fa23d773cae35a188f753570fd4ad67b0751 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java @@ -37,12 +37,12 @@ import com.oracle.truffle.r.runtime.ffi.RFFIFactory; import com.oracle.truffle.r.runtime.ffi.ToolsRFFI; public class Generic_Tools implements ToolsRFFI { - private static class Generic_ToolsRFFINode extends ParseRdNode { + public static class Generic_ToolsRFFINode extends ParseRdNode { private static final String C_PARSE_RD = "C_parseRd"; - private static final String TOOLS = "tools"; + protected static final String TOOLS = "tools"; @Child private CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode(); - @Child DLL.RFindSymbolNode findSymbolNode = DLL.RFindSymbolNode.create(); + @Child private DLL.RFindSymbolNode findSymbolNode = DLL.RFindSymbolNode.create(); @CompilationFinal private NativeCallInfo nativeCallInfo; diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java index f729327ebae99dc51f3e1a81c316acc35eb1d7ff..115c562a7da08795f749b39c9bc216158940bdb1 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java @@ -59,20 +59,39 @@ public class JNI_Call implements CallRFFI { } try { switch (args.length) { - // @formatter:off - case 0: result = call0(address); break; - case 1: result = call1(address, args[0]); break; - case 2: result = call2(address, args[0], args[1]); break; - case 3: result = call3(address, args[0], args[1], args[2]); break; - case 4: result = call4(address, args[0], args[1], args[2], args[3]); break; - case 5: result = call5(address, args[0], args[1], args[2], args[3], args[4]); break; - case 6: result = call6(address, args[0], args[1], args[2], args[3], args[4], args[5]); break; - case 7: result = call7(address, args[0], args[1], args[2], args[3], args[4], args[5], args[6]); break; - case 8: result = call8(address, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); break; - case 9: result = call9(address, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); break; + case 0: + result = call0(address); + break; + case 1: + result = call1(address, args[0]); + break; + case 2: + result = call2(address, args[0], args[1]); + break; + case 3: + result = call3(address, args[0], args[1], args[2]); + break; + case 4: + result = call4(address, args[0], args[1], args[2], args[3]); + break; + case 5: + result = call5(address, args[0], args[1], args[2], args[3], args[4]); + break; + case 6: + result = call6(address, args[0], args[1], args[2], args[3], args[4], args[5]); + break; + case 7: + result = call7(address, args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + break; + case 8: + result = call8(address, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); + break; + case 9: + result = call9(address, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); + break; default: - result = call(address, args); break; - // @formatter:on + result = call(address, args); + break; } return result; } finally { diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java index 7b0a29a0be58fd01a27701d12c1644b9c192da9e..25c8ad506d1ed729b4a48e73f32bd1b2938fd8fd 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.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 @@ -26,83 +26,173 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.ffi.LapackRFFI; public class JNI_Lapack implements LapackRFFI { - private static class JNI_LapackRFFINode extends LapackRFFINode { + private static class JNI_IlaverNode extends IlaverNode { @Override @TruffleBoundary - public void ilaver(int[] version) { + public void execute(int[] version) { native_ilaver(version); } + } + private static class JNI_DgeevNode extends DgeevNode { @Override @TruffleBoundary - public int dgeev(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork) { + public int execute(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork) { return native_dgeev(jobVL, jobVR, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork); } + } + private static class JNI_Dgeqp3Node extends Dgeqp3Node { @Override @TruffleBoundary - public int dgeqp3(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork) { + public int execute(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork) { return native_dgeqp3(m, n, a, lda, jpvt, tau, work, lwork); } + } + private static class JNI_DormqrNode extends DormqrNode { @Override @TruffleBoundary - public int dormqr(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork) { + public int execute(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork) { return native_dormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork); } + } + private static class JNI_DtrtrsNode extends DtrtrsNode { @Override @TruffleBoundary - public int dtrtrs(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb) { + public int execute(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb) { return native_dtrtrs(uplo, trans, diag, n, nrhs, a, lda, b, ldb); } + } + private static class JNI_DgetrfNode extends DgetrfNode { @Override @TruffleBoundary - public int dgetrf(int m, int n, double[] a, int lda, int[] ipiv) { + public int execute(int m, int n, double[] a, int lda, int[] ipiv) { return native_dgetrf(m, n, a, lda, ipiv); } + } + private static class JNI_DpotrfNode extends DpotrfNode { @Override @TruffleBoundary - public int dpotrf(char uplo, int n, double[] a, int lda) { + public int execute(char uplo, int n, double[] a, int lda) { return native_dpotrf(uplo, n, a, lda); } + } + + private static class JNI_DpotriNode extends DpotriNode { + @Override + @TruffleBoundary + public int execute(char uplo, int n, double[] a, int lda) { + return native_dpotri(uplo, n, a, lda); + } + } + private static class JNI_DpstrfNode extends DpstrfNode { @Override @TruffleBoundary - public int dpstrf(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work) { + public int execute(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work) { return native_dpstrf(uplo, n, a, lda, piv, rank, tol, work); } + } + private static class JNI_DgesvNode extends DgesvNode { @Override @TruffleBoundary - public int dgesv(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb) { + public int execute(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb) { return native_dgesv(n, nrhs, a, lda, ipiv, b, ldb); } + } + private static class JNI_DlangeNode extends DlangeNode { @Override @TruffleBoundary - public double dlange(char norm, int m, int n, double[] a, int lda, double[] work) { + public double execute(char norm, int m, int n, double[] a, int lda, double[] work) { return native_dlange(norm, m, n, a, lda, work); } + } + private static class JNI_DgeconNode extends DgeconNode { @Override @TruffleBoundary - public int dgecon(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork) { + public int execute(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork) { return native_dgecon(norm, n, a, lda, anorm, rcond, work, iwork); } + } + private static class JNI_DsyevrNode extends DsyevrNode { @Override - public int dsyevr(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, + public int execute(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, double[] w, double[] z, int ldz, int[] isuppz, double[] work, int lwork, int[] iwork, int liwork) { return native_dsyevr(jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w, z, ldz, isuppz, work, lwork, iwork, liwork); } } @Override - public LapackRFFINode createLapackRFFINode() { - return new JNI_LapackRFFINode(); + public IlaverNode createIlaverNode() { + return new JNI_IlaverNode(); + } + + @Override + public DgeevNode createDgeevNode() { + return new JNI_DgeevNode(); + } + + @Override + public Dgeqp3Node createDgeqp3Node() { + return new JNI_Dgeqp3Node(); + } + + @Override + public DormqrNode createDormqrNode() { + return new JNI_DormqrNode(); + } + + @Override + public DtrtrsNode createDtrtrsNode() { + return new JNI_DtrtrsNode(); + } + + @Override + public DgetrfNode createDgetrfNode() { + return new JNI_DgetrfNode(); + } + + @Override + public DpotrfNode createDpotrfNode() { + return new JNI_DpotrfNode(); + } + + @Override + public DpotriNode createDpotriNode() { + return new JNI_DpotriNode(); + } + + @Override + public DpstrfNode createDpstrfNode() { + return new JNI_DpstrfNode(); + } + + @Override + public DgesvNode createDgesvNode() { + return new JNI_DgesvNode(); + } + + @Override + public DlangeNode createDlangeNode() { + return new JNI_DlangeNode(); + } + + @Override + public DgeconNode createDgeconNode() { + return new JNI_DgeconNode(); + } + + @Override + public DsyevrNode createDsyevrNode() { + return new JNI_DsyevrNode(); } // Checkstyle: stop method name @@ -121,6 +211,8 @@ public class JNI_Lapack implements LapackRFFI { private static native int native_dpotrf(char uplo, int n, double[] a, int lda); + private static native int native_dpotri(char uplo, int n, double[] a, int lda); + private static native int native_dpstrf(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work); private static native int native_dgesv(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb); diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java index 25035bfc14be70f11f84b916ffb519ac8281e4eb..1e4ae3a4ac0ed422652785418e429c479ca48bc8 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java @@ -30,20 +30,27 @@ import com.oracle.truffle.r.runtime.ffi.MiscRFFI; public class JNI_Misc implements MiscRFFI { - @Override - public double exactSum(double[] values, boolean hasNa, boolean naRm) { - if (traceEnabled()) { - traceDownCall("exactSum"); - } - try { - return exactSumFunc(values, hasNa, naRm); - } finally { + private static class JNI_ExactSumNode extends ExactSumNode { + @Override + public double execute(double[] values, boolean hasNa, boolean naRm) { if (traceEnabled()) { - traceDownCallReturn("exactSum", null); + traceDownCall("exactSum"); + } + try { + return exactSumFunc(values, hasNa, naRm); + } finally { + if (traceEnabled()) { + traceDownCallReturn("exactSum", null); + } } } } + @Override + public ExactSumNode createExactSumNode() { + return new JNI_ExactSumNode(); + } + private static native double exactSumFunc(double[] values, boolean hasNa, boolean naRm); } diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RAppl.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RAppl.java index 995c4d0914be9d4c7a26355f15cf063fcc3a1cfe..bf64d0c96dab3d70eb3820c4d6a6c83d7646413f 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RAppl.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RAppl.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 @@ -26,30 +26,46 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.ffi.RApplRFFI; public class JNI_RAppl implements RApplRFFI { - private static class JNI_RApplRFFINode extends RApplRFFINode { + private static class JNI_Dqrdc2Node extends Dqrdc2Node { @Override @TruffleBoundary - public void dqrdc2(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work) { + public void execute(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work) { native_dqrdc2(x, ldx, n, p, tol, rank, qraux, pivot, work); } + } + + private static class JNI_DqrcfNode extends DqrcfNode { @Override @TruffleBoundary - public void dqrcf(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info) { + public void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info) { native_dqrcf(x, n, k, qraux, y, ny, b, info); } + } + private static class JNI_DqrlsNode extends DqrlsNode { @Override @TruffleBoundary - public void dqrls(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work) { + public void execute(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work) { native_dqrls(x, n, p, y, ny, tol, b, rsd, qty, k, jpvt, qraux, work); } } @Override - public RApplRFFINode createRApplRFFINode() { - return new JNI_RApplRFFINode(); + public Dqrdc2Node createDqrdc2Node() { + return new JNI_Dqrdc2Node(); + } + + @Override + public DqrcfNode createDqrcfNode() { + return new JNI_DqrcfNode(); } + + @Override + public DqrlsNode createDqrlsNode() { + return new JNI_DqrlsNode(); + } + // Checkstyle: stop method name private static native void native_dqrdc2(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work); diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java index 28f516f7c64c2464ff43763a4b5370b273d449f5..0ec293f8b14f4418dada70b7b8d28912b033fb39 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java @@ -31,7 +31,6 @@ import com.oracle.truffle.r.runtime.ffi.CRFFI; import com.oracle.truffle.r.runtime.ffi.CallRFFI; import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.DLLRFFI; -import com.oracle.truffle.r.runtime.ffi.GridRFFI; import com.oracle.truffle.r.runtime.ffi.LapackRFFI; import com.oracle.truffle.r.runtime.ffi.LibPaths; import com.oracle.truffle.r.runtime.ffi.MiscRFFI; @@ -44,7 +43,6 @@ import com.oracle.truffle.r.runtime.ffi.StatsRFFI; import com.oracle.truffle.r.runtime.ffi.ToolsRFFI; import com.oracle.truffle.r.runtime.ffi.UserRngRFFI; import com.oracle.truffle.r.runtime.ffi.ZipRFFI; -import com.oracle.truffle.r.runtime.ffi.generic.Generic_Grid; import com.oracle.truffle.r.runtime.ffi.generic.Generic_Tools; /** @@ -146,17 +144,6 @@ public class JNI_RFFIFactory extends RFFIFactory implements RFFI { return toolsRFFI; } - @CompilationFinal private GridRFFI gridRFFI; - - @Override - public GridRFFI getGridRFFI() { - if (gridRFFI == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - gridRFFI = new Generic_Grid(); - } - return gridRFFI; - } - @CompilationFinal private UserRngRFFI userRngRFFI; @Override diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/DCF.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/DCF.java index 5f5fa9f83c5020a13f274dd3613ff463547e7d5e..48069f9e2f3c9bf380ae917a6b8ba067f7df656e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/DCF.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/DCF.java @@ -70,8 +70,11 @@ public class DCF { fieldContent = new StringBuffer(); } if (endOfParagraph(line)) { - result.paragraphs.add(fields); - fields = new Fields(); + fieldName = null; + if (!fields.fieldMap.isEmpty()) { + result.paragraphs.add(fields); + fields = new Fields(); + } continue; } int ix = line.indexOf(':'); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastRConfig.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastRConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..8d6bbf8f1bf32640ec626bed909b96e80c31e37f --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastRConfig.java @@ -0,0 +1,52 @@ +/* + * 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.runtime; + +public final class FastRConfig { + /** + * Whether the internal grid emulation should use AWT backed graphical devices. + */ + public static final boolean InternalGridAwtSupport; + + /** + * Umbrella option, which changes default values of other options in a way that FastR will not + * invoke any native code directly and other potentially security sensitive operations are + * restricted. Can be configured via environment variable {@code FASTR_MANAGED}. + */ + public static final boolean ManagedMode; + + static { + String managedModeVal = System.getenv("FASTR_MANAGED"); + ManagedMode = managedModeVal != null && managedModeVal.equals("true"); + if (ManagedMode) { + InternalGridAwtSupport = false; + } else { + String val = System.getProperty("fastr.internal.grid.awt.support"); + InternalGridAwtSupport = val == null || val.equals("true"); + } + } + + private FastRConfig() { + // only static fields + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java index 925e1f39042c3510b80c4d18eb2f1cdbcb18bd93..ad7e272e9177f545a3da27dbd88495501d6d1751 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java @@ -46,14 +46,20 @@ public enum FastROptions { TraceNativeCalls("Trace all native function calls (performed via .Call, .External, etc.)", false), Rdebug("Rdebug=f1,f2.,,,; list of R function to call debug on (implies +Instrument)", null, true), PerformanceWarnings("Print FastR performance warning", false), - LoadBase("Load base package", true), + LoadProfiles("Load the system, site and user profile scripts.", !FastRConfig.ManagedMode), PrintComplexLookups("Print a message for each non-trivial variable lookup", false), FullPrecisionSum("Use 128 bit arithmetic in sum builtin", false), InvisibleArgs("Argument writes do not trigger state transitions", true), RefCountIncrementOnly("Disable reference count decrements for experimental state transition implementation", false), - UseInternalGraphics("Whether the internal (Java) graphics subsystem should be used", false), + UseInternalGridGraphics("Whether the internal (Java) grid graphics implementation should be used", true), UseSpecials("Whether the fast-path special call nodes should be created for simple enough arguments.", true), ForceSources("Generate source sections for unserialized code", false), + SharedContexts("Whether all child contexts are to be shared contexts", true), + SearchPathForcePromises("Whether all promises for frames on shared path are forced in presence of shared contexts", false), + LoadPackagesNativeCode("Load native code of packages, including builtin packages.", !FastRConfig.ManagedMode), + EmitTmpSource("Write deparsed source code to temporary files for better debugging.", true), + EmitTmpDir("The directory where to allocate temporary files with deparsed source code.", null, true), + EmitTmpHashed("Use an SHA-256 hash as file name to reduce temporary file creation.", true), // Promises optimizations EagerEval("If enabled, overrides all other EagerEval switches (see EagerEvalHelper)", false), @@ -81,8 +87,9 @@ public enum FastROptions { public boolean getBooleanValue() { assert isBoolean; - if (value instanceof Boolean) { - return (Boolean) value; + Object v = value; + if (v instanceof Boolean) { + return (boolean) v; } else { CompilerDirectives.transferToInterpreter(); System.out.println("boolean option value expected with " + name() + " - forgot +/- ?"); @@ -93,8 +100,9 @@ public enum FastROptions { public String getStringValue() { assert !isBoolean; - if (value == null || value instanceof String) { - return (String) value; + Object v = value; + if (v == null || v instanceof String) { + return (String) v; } else { CompilerDirectives.transferToInterpreter(); System.out.println("string option value expected with " + name()); @@ -105,13 +113,14 @@ public enum FastROptions { public int getNonNegativeIntValue() { assert !isBoolean; - if (value instanceof Integer) { - return (Integer) value; + Object v = value; + if (v instanceof Integer) { + return (Integer) v; } CompilerDirectives.transferToInterpreterAndInvalidate(); - if (value instanceof String) { + if (v instanceof String) { try { - int res = Integer.decode((String) value); + int res = Integer.decode((String) v); if (res >= 0) { value = res; return res; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/DefaultResourceHandlerFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/LazyResourceHandlerFactory.java similarity index 98% rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/DefaultResourceHandlerFactory.java rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/LazyResourceHandlerFactory.java index 618db886292158291c7492907638055b3bd57215..1befec1946704fddf99e8ecaf103d574c95feff0 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/DefaultResourceHandlerFactory.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/LazyResourceHandlerFactory.java @@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.ResourceHandlerFactory.Handler; /** * Default implementation uses the default mechanism in {@code java.lang.Class}. */ -class DefaultResourceHandlerFactory extends ResourceHandlerFactory implements Handler { +class LazyResourceHandlerFactory extends ResourceHandlerFactory implements Handler { @Override public URL getResource(Class<?> accessor, String name) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrettyIntevals.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrettyIntevals.java new file mode 100644 index 0000000000000000000000000000000000000000..9ff10b704e4d1081c3428ab59cd5977bd756e0f7 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrettyIntevals.java @@ -0,0 +1,166 @@ +/* + * 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) 1995, 1996 Robert Gentleman and Ross Ihaka + * Copyright (c) 1997-2014, The R Core Team + * Copyright (c) 2016, 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.runtime; + +import com.oracle.truffle.r.runtime.nodes.RBaseNode; + +/** + * Constructs m "pretty" values which cover the given interval. This code is used in both built-in + * {@code pretty} and the grid package. + */ +public final class PrettyIntevals { + private PrettyIntevals() { + // only static members + } + + // transcribed from pretty.c + + public static double pretty(RBaseNode errorCtx, double[] lo, double[] up, int[] ndiv, int minN, + double shrinkSml, double[] highUFact, + int epsCorrection, boolean returnBounds) { + /* + * From version 0.65 on, we had rounding_eps := 1e-5, before, r..eps = 0 1e-7 is consistent + * with seq.default() + */ + double roundingEps = 1e-7; + + double h = highUFact[0]; + double h5 = highUFact[1]; + + double dx; + double cell; + double unit; + double base; + double uu; + double ns; + double nu; + int k; + boolean iSmall; + + dx = up[0] - lo[0]; + /* cell := "scale" here */ + if (dx == 0 && up[0] == 0) { /* up == lo == 0 */ + cell = 1; + iSmall = true; + } else { + cell = Math.max(Math.abs(lo[0]), Math.abs(up[0])); + /* uu = upper bound on cell/unit */ + // uu = (1 + (h5 >= 1.5 * h + .5)) ? 1 / (1 + h) : 1.5 / (1 + h5); + // How can above expression ever be zero? + uu = 1 / (1 + h); + /* added times 3, as several calculations here */ + iSmall = dx < cell * uu * Math.max(1, ndiv[0]) * RRuntime.EPSILON * 3; + } + + /* OLD: cell = FLT_EPSILON+ dx / ndiv[0]; FLT_EPSILON = 1.192e-07 */ + if (iSmall) { + if (cell > 10) { + cell = 9 + cell / 10; + } + cell *= shrinkSml; + if (minN > 1) { + cell /= minN; + } + } else { + cell = dx; + if (ndiv[0] > 1) { + cell /= ndiv[0]; + } + } + + if (cell < 20 * Double.MIN_VALUE) { + RError.warning(errorCtx, RError.Message.GENERIC, "Internal(pretty()): very small range.. corrected"); + cell = 20 * Double.MIN_VALUE; + } else if (cell * 10 > Double.MAX_VALUE) { + RError.warning(errorCtx, RError.Message.GENERIC, "Internal(pretty()): very large range.. corrected"); + cell = .1 * Double.MAX_VALUE; + } + /* + * NB: the power can be negative and this relies on exact calculation, which glibc's exp10 + * does not achieve + */ + base = Math.pow(10.0, Math.floor(Math.log10(cell))); /* base <= cell < 10*base */ + + /* + * unit : from { 1,2,5,10 } * base such that |u - cell| is small, favoring larger (if h > 1, + * else smaller) u values; favor '5' more than '2' if h5 > h (default h5 = .5 + 1.5 h) + */ + unit = base; + if ((uu = 2 * base) - cell < h * (cell - unit)) { + unit = uu; + if ((uu = 5 * base) - cell < h5 * (cell - unit)) { + unit = uu; + if ((uu = 10 * base) - cell < h * (cell - unit)) { + unit = uu; + } + } + } + /* + * Result: c := cell, u := unit, b := base c in [ 1, (2+ h) /(1+h) ] b ==> u= b c in ( (2+ + * h)/(1+h), (5+2h5)/(1+h5)] b ==> u= 2b c in ( (5+2h)/(1+h), (10+5h) /(1+h) ] b ==> u= 5b c + * in ((10+5h)/(1+h), 10 ) b ==> u=10b + * + * ===> 2/5 *(2+h)/(1+h) <= c/u <= (2+h)/(1+h) + */ + + ns = Math.floor(lo[0] / unit + roundingEps); + nu = Math.ceil(up[0] / unit - roundingEps); + if (epsCorrection != 0 && (epsCorrection > 1 || !iSmall)) { + if (lo[0] != 0.) { + lo[0] *= (1 - RRuntime.EPSILON); + } else { + lo[0] = -Double.MIN_VALUE; + } + if (up[0] != 0.) { + up[0] *= (1 + RRuntime.EPSILON); + } else { + up[0] = +Double.MIN_VALUE; + } + } + + while (ns * unit > lo[0] + roundingEps * unit) { + ns--; + } + + while (nu * unit < up[0] - roundingEps * unit) { + nu++; + } + + k = (int) (0.5 + nu - ns); + if (k < minN) { + /* ensure that nu - ns == min_n */ + k = minN - k; + if (ns >= 0.) { + nu += k / 2; + ns -= k / 2 + k % 2; /* ==> nu-ns = old(nu-ns) + min_n -k = min_n */ + } else { + ns -= k / 2; + nu += k / 2 + k % 2; + } + ndiv[0] = minN; + } else { + ndiv[0] = k; + } + if (returnBounds) { /* if()'s to ensure that result covers original range */ + if (ns * unit < lo[0]) { + lo[0] = ns * unit; + } + if (nu * unit > up[0]) { + up[0] = nu * unit; + } + } else { + lo[0] = ns; + up[0] = nu; + } + return unit; + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrimitiveMethodsInfo.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrimitiveMethodsInfo.java index 6aa68c5ba2280ac48ee2922ca2f7c5087c29a631..76d5a6bea1c42f90143adec8441e632603f07259 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrimitiveMethodsInfo.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrimitiveMethodsInfo.java @@ -6,7 +6,7 @@ * Copyright (c) 1995, 1996, 1997 Robert Gentleman and Ross Ihaka * Copyright (c) 1995-2014, The R Core Team * Copyright (c) 2002-2008, The R Foundation - * Copyright (c) 2016, Oracle and/or its affiliates + * Copyright (c) 2016, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -52,7 +52,7 @@ public class PrimitiveMethodsInfo { } public RFunction getPrimGeneric(int index) { - return primGenerics[index]; + return index < primGenerics.length ? primGenerics[index] : null; } public void setPrimGeneric(int index, RFunction generic) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java index aeec6146425d173a9004ff1e1e5de3a3d74edde7..1f41cbf04d1065e45362ffe5744d36e0c2a93e65 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.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 @@ -28,6 +28,7 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.ValueType; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.MaterializedFrame; +import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.env.REnvironment; @@ -272,6 +273,10 @@ public final class RArguments { return (MaterializedFrame) frame.getArguments()[INDEX_ENCLOSING_FRAME]; } + public static ArgumentsSignature getSignature(Frame frame, ValueProfile functionProfile) { + return functionProfile.profile((HasSignature) getFunction(frame).getRootNode()).getSignature(); + } + public static ArgumentsSignature getSignature(Frame frame) { return ((HasSignature) getFunction(frame).getRootNode()).getSignature(); } @@ -288,12 +293,14 @@ public final class RArguments { frame.getArguments()[INDEX_IS_IRREGULAR] = isIrregularFrame; } - public static void setEnclosingFrame(Frame frame, MaterializedFrame newEnclosingFrame) { + public static void setEnclosingFrame(Frame frame, MaterializedFrame newEnclosingFrame, boolean updateDescriptors) { CompilerAsserts.neverPartOfCompilation(); Object[] arguments = frame.getArguments(); MaterializedFrame oldEnclosingFrame = (MaterializedFrame) arguments[INDEX_ENCLOSING_FRAME]; arguments[INDEX_ENCLOSING_FRAME] = newEnclosingFrame; - FrameSlotChangeMonitor.setEnclosingFrame(frame, newEnclosingFrame, oldEnclosingFrame); + if (updateDescriptors) { + FrameSlotChangeMonitor.setEnclosingFrame(frame, newEnclosingFrame, oldEnclosingFrame); + } } public static void initializeEnclosingFrame(Frame frame, MaterializedFrame newEnclosingFrame) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java index 595a9c69e2ecea41e936c904830f9792b6251517..bc1cb211f156e4c0a9e698fd1cf9b945af97b894 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java @@ -28,8 +28,10 @@ import java.util.concurrent.Semaphore; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; +import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.object.DynamicObject; +import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor; import com.oracle.truffle.r.runtime.conn.RConnection; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RAttributable; @@ -242,11 +244,15 @@ public class RChannel { // parent can be SerializedEnv or byte[] private final Object parent; private final DynamicObject attributes; + private final String name; + private final FrameDescriptor desc; - SerializedEnv(Bindings bindings, Object parent, DynamicObject attributes) { + SerializedEnv(Bindings bindings, Object parent, DynamicObject attributes, String name, FrameDescriptor desc) { this.bindings = bindings; this.parent = parent; this.attributes = attributes; + this.name = name; + this.desc = desc; } public String[] getNames() { @@ -264,6 +270,14 @@ public class RChannel { public DynamicObject getAttributes() { return attributes; } + + public String getName() { + return name; + } + + public FrameDescriptor getDesc() { + return desc; + } } protected static class SerializedPromise { @@ -294,12 +308,18 @@ public class RChannel { protected static class SerializedFunction { private final DynamicObject attributes; private final Object env; - private final RFunction serializedDef; + private final String name; + private final String packageName; + private final RBuiltinDescriptor builtinDesc; + private final RootCallTarget callTarget; - public SerializedFunction(DynamicObject attributes, Object env, RFunction serializedDef) { + public SerializedFunction(DynamicObject attributes, Object env, String name, String packageName, RBuiltinDescriptor builtinDesc, RootCallTarget callTarget) { this.attributes = attributes; this.env = env; - this.serializedDef = serializedDef; + this.name = name; + this.packageName = packageName; + this.builtinDesc = builtinDesc; + this.callTarget = callTarget; } public DynamicObject getAttributes() { @@ -310,8 +330,20 @@ public class RChannel { return env; } - public RFunction getSerializedDef() { - return serializedDef; + public String getName() { + return name; + } + + public RBuiltinDescriptor getRBuiltin() { + return builtinDesc; + } + + public RootCallTarget getTarget() { + return callTarget; + } + + public String getPackageName() { + return packageName; } } @@ -394,6 +426,7 @@ public class RChannel { } } + @TruffleBoundary private Object convertPrivateEnv(Object msg) throws IOException { int refInd = getRefIndex(msg); if (refInd != -1) { @@ -408,7 +441,7 @@ public class RChannel { } SerializedEnv.Bindings bindings = createShareable(env); - return new SerializedEnv(bindings, convertPrivateSlow(env.getParent()), attributes); + return new SerializedEnv(bindings, convertPrivateSlow(env.getParent()), attributes, env.getName(), env.getFrame().getFrameDescriptor()); } private SerializedPromise convertPrivatePromise(Object msg) throws IOException { @@ -425,7 +458,7 @@ public class RChannel { RFunction fn = (RFunction) msg; Object env = convertPrivate(REnvironment.frameToEnvironment(fn.getEnclosingFrame())); DynamicObject attributes = fn.getAttributes(); - return new SerializedFunction(attributes == null ? null : createShareableSlow(attributes, true), env, fn); + return new SerializedFunction(attributes == null ? null : createShareableSlow(attributes, true), env, fn.getName(), fn.getPackageName(), fn.getRBuiltin(), fn.getTarget()); } private Object convertPrivateAttributable(Object msg) throws IOException { @@ -603,7 +636,7 @@ public class RChannel { Object[] values = e.getValues(); String[] names = e.getNames(); assert values.length == names.length; - REnvironment.NewEnv env = RDataFactory.createNewEnv(null); + REnvironment.NewEnv env = RDataFactory.createNewEnv(e.getDesc(), e.getName()); addReadRef(env); int ind = 0; for (String n : names) { @@ -611,7 +644,7 @@ public class RChannel { env.safePut(n, newValue); } REnvironment parent = (REnvironment) unserializeObject(e.getParent()); - RArguments.initializeEnclosingFrame(env.getFrame(), parent.getFrame()); + RArguments.setEnclosingFrame(env.getFrame(), parent.getFrame(), false); DynamicObject attributes = e.getAttributes(); if (attributes != null) { env.initAttributes(attributes); @@ -636,13 +669,17 @@ public class RChannel { @TruffleBoundary private RFunction unserializeFunction(SerializedFunction f) throws IOException { - RFunction fun = f.getSerializedDef(); REnvironment env = (REnvironment) unserializeObject(f.getEnv()); MaterializedFrame enclosingFrame = env.getFrame(); - HasSignature root = (HasSignature) fun.getTarget().getRootNode(); - RootCallTarget target = root.duplicateWithNewFrameDescriptor(); - FrameSlotChangeMonitor.initializeEnclosingFrame(target.getRootNode().getFrameDescriptor(), enclosingFrame); - RFunction fn = RDataFactory.createFunction(fun.getName(), fun.getPackageName(), target, null, enclosingFrame); + RFunction fn; + if (FastROptions.SharedContexts.getBooleanValue()) { + fn = RDataFactory.createFunction(f.getName(), f.getPackageName(), f.getTarget(), f.getRBuiltin(), enclosingFrame); + } else { + HasSignature root = (HasSignature) f.getTarget().getRootNode(); + RootCallTarget target = root.duplicateWithNewFrameDescriptor(); + FrameSlotChangeMonitor.initializeEnclosingFrame(target.getRootNode().getFrameDescriptor(), enclosingFrame); + fn = RDataFactory.createFunction(f.getName(), f.getPackageName(), target, null, enclosingFrame); + } DynamicObject attributes = f.getAttributes(); if (attributes != null) { assert fn.getAttributes() == null; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java index 3e303f3c0ecc0ebc8d6e602a23a5d8a95873d045..436e252e5d8d79ff47af6ab934fa9aeffa0e6275 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java @@ -104,8 +104,7 @@ public class RCleanUp { RInternalError.reportError(t); } } - // TODO run exit finalizers (FFI) - // TODO clean tmpdir + // TODO run exit finalizers (FFI) (this should happen in the FFI context beforeDestroy) throw new ExitException(status); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java index a1d9f81682824f9db676bb090289431879662522..b80c2f0d91394557a75151b63c341b280c201d4b 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java @@ -212,6 +212,8 @@ public class RCompression { if (rc == 0) { readThread.join(); return Arrays.copyOf(readThread.getData(), readThread.getTotalRead()); + } else { + throw new IOException("bzip2 error code: " + rc); } } catch (InterruptedException ex) { // fall through @@ -239,6 +241,8 @@ public class RCompression { OpenOption[] openOptions = append ? new OpenOption[]{StandardOpenOption.APPEND} : new OpenOption[0]; Files.write(Paths.get(path), cData, openOptions); return; + } else { + throw new IOException("bzip2 error code: " + rc); } } catch (InterruptedException ex) { // fall through 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 9c8ae0753becbf5e23ab8d663366ce364e93f35c..7c250e88e7fb001ded28431cf715138ffc026fcf 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 @@ -11,13 +11,26 @@ */ package com.oracle.truffle.r.runtime; +import static java.nio.file.StandardOpenOption.CREATE_NEW; +import static java.nio.file.StandardOpenOption.WRITE; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; 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; import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; @@ -37,6 +50,7 @@ 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.RRaw; import com.oracle.truffle.r.runtime.data.RS4Object; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RSymbol; @@ -315,13 +329,71 @@ public class RDeparse { } } + private static MessageDigest digest = null; + + private Path emitToFile(String qualifiedFunctionName) throws IOException, NoSuchAlgorithmException { + Path tmpDir = Paths.get(Utils.getUserTempDir()).resolve("deparse"); + if (!Files.exists(tmpDir)) { + Files.createDirectory(tmpDir); + } + + Path path; + if (FastROptions.EmitTmpHashed.getBooleanValue()) { + if (digest == null) { + digest = MessageDigest.getInstance("SHA-256"); + } + String printHexBinary = DatatypeConverter.printHexBinary(digest.digest(sb.toString().getBytes())); + assert printHexBinary.length() > 10; + + // just use the first 10 hex digits to have a nicer file name + if (qualifiedFunctionName != null && !qualifiedFunctionName.isEmpty() && !qualifiedFunctionName.equals("<no source>")) { + path = tmpDir.resolve(qualifiedFunctionName + "-" + printHexBinary.substring(0, 10) + ".r"); + } else { + path = tmpDir.resolve(printHexBinary.substring(0, 10) + ".r"); + } + } else { + path = Files.createTempFile("deparse-", ".r"); + } + if (!Files.exists(path)) { + try (BufferedWriter bw = Files.newBufferedWriter(path, CREATE_NEW, WRITE)) { + bw.write(sb.toString()); + } + } + return path; + } + public void fixupSources() { - Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.DEPARSE); - for (SourceSectionElement s : sources) { - s.element.setSourceSection(source.createSection(s.start, s.length)); + if (FastROptions.EmitTmpSource.getBooleanValue()) { + try { + RootNode rootNode = getRootNode(); + String name = rootNode != null ? rootNode.getName() : null; + Path path = emitToFile(name); + Source source = RSource.fromFile(path.toFile()); + for (SourceSectionElement s : sources) { + s.element.setSourceSection(source.createSection(s.start, s.length)); + } + } catch (IOException e) { + RInternalError.reportError(e); + } catch (NoSuchAlgorithmException e) { + throw RInternalError.shouldNotReachHere("SHA-256 is an unknown algorithm"); + } + } else { + Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.DEPARSE); + for (SourceSectionElement s : sources) { + s.element.setSourceSection(source.createSection(s.start, s.length)); + } } } + private RootNode getRootNode() { + // the last element in the list is the top-most one + RSyntaxElement n = sources.get(sources.size() - 1).element; + if (n instanceof RootNode) { + return (RootNode) n; + } + return null; + } + @SuppressWarnings("try") private DeparseVisitor append(String str, RSyntaxElement... context) { try (C c = withContext(context)) { @@ -577,24 +649,22 @@ public class RDeparse { case BINARY: case BINARY2: RSyntaxElement[] subArgs = ((RSyntaxCall) arg).getSyntaxArguments(); - if (subArgs.length > 2) { - needsParens = false; - break; - } if (subArgs.length == 1) { - if (!isLeft) { + if (!isLeft && (arginfo.prec != RDeparse.PREC_NOT || mainOp.prec != RDeparse.PREC_NOT)) { needsParens = false; break; } if (arginfo.prec == RDeparse.PREC_SUM) { arginfo = arginfo.changePrec(RDeparse.PREC_SIGN); } - } - if (subArgs.length == 2) { + } else if (subArgs.length == 2) { if (mainOp.prec == PREC_COMPARE && arginfo.prec == PREC_COMPARE) { needsParens = true; break; } + } else if (subArgs.length > 2) { + needsParens = false; + break; } needsParens = mainOp.prec > arginfo.prec || (mainOp.prec == arginfo.prec && isLeft == mainOp.rightassoc); break; @@ -641,7 +711,7 @@ public class RDeparse { } } else if (value instanceof RPairList) { RPairList arglist = (RPairList) value; - assert arglist.getType() == SEXPTYPE.LISTSXP; + assert arglist.getType() == null || arglist.getType() == SEXPTYPE.LISTSXP : arglist.getType(); append("pairlist("); int i = 0; boolean lbreak = false; @@ -681,6 +751,8 @@ public class RDeparse { append("<pointer: 0x").append(Long.toHexString(((RExternalPtr) value).getAddr().asAddress())).append('>'); } else if (value instanceof REnvironment) { append("<environment>"); + } else if (value instanceof REmpty) { + append(""); } else if (value instanceof TruffleObject) { append("<truffle object>"); } else { @@ -791,15 +863,25 @@ public class RDeparse { return; } else { // TODO COMPAT? - append("c("); - for (int i = 0; i < len; i++) { - Object element = vec.getDataAtAsObject(i); - vecElement2buff(type, element, false); - if (i < len - 1) { - append(", "); + if (type == SEXPTYPE.RAWSXP) { + append("as.raw(c("); + for (int i = 0; i < len; i++) { + if (i > 0) { + append(", "); + } + vecElement2buff(type, vec.getDataAtAsObject(i), false); } + append("))"); + } else { + append("c("); + for (int i = 0; i < len; i++) { + if (i > 0) { + append(", "); + } + vecElement2buff(type, vec.getDataAtAsObject(i), false); + } + append(')'); } - append(')'); } } } @@ -830,7 +912,7 @@ public class RDeparse { switch (type) { case STRSXP: String s = (String) element; - append(RRuntime.isNA(s) ? (singleElement ? "NA_character_" : "NA") : RRuntime.quoteString((String) element, true)); + append(RRuntime.isNA(s) ? (singleElement ? "NA_character_" : "NA") : RRuntime.escapeString(s, true, true)); break; case LGLSXP: append(RRuntime.logicalToString((byte) element)); @@ -858,6 +940,10 @@ public class RDeparse { append(RContext.getRRuntimeASTAccess().encodeComplex(c)); } break; + case RAWSXP: + RRaw r = (RRaw) element; + append(Utils.stringFormat("0x%02x", r.getValue())); + break; default: throw RInternalError.shouldNotReachHere("unexpected SEXPTYPE: " + type); } @@ -878,7 +964,7 @@ public class RDeparse { } lbreak = linebreak(lbreak); if (snames != null) { - append(snames.getDataAt(i)); + append(quotify(snames.getDataAt(i), '\"')); append(" = "); } appendValue(v.getDataAtAsObject(i)); @@ -930,7 +1016,6 @@ public class RDeparse { break; default: { - opts = SIMPLEDEPARSE; if (attrName.contains(" ")) { append('"'); append(attrName); @@ -973,10 +1058,24 @@ public class RDeparse { /** * Ensure that {@code node} has a {@link SourceSection} by deparsing if necessary. */ + @TruffleBoundary public static void ensureSourceSection(RSyntaxNode node) { SourceSection ss = node.getLazySourceSection(); if (ss == RSyntaxNode.LAZY_DEPARSE) { - new DeparseVisitor(true, RDeparse.MAX_Cutoff, false, -1, 0).append(node).fixupSources(); + RSyntaxElement nodeToFixup = node; + if (FastROptions.EmitTmpSource.getBooleanValue()) { + RootNode rootNode = node.asNode().getRootNode(); + if (RContext.getRRuntimeASTAccess().isFunctionDefinitionNode(rootNode)) { + nodeToFixup = (RSyntaxElement) rootNode; + } + } + // 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(); + + // 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(); + } assert node.getLazySourceSection() != RSyntaxNode.LAZY_DEPARSE; } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java index 86e5fd3060d651cf32dabc5af790f02b2f28b6bd..87fcb60bbdc6016d67d2e0aaef48f0264062cfe9 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java @@ -22,6 +22,8 @@ */ package com.oracle.truffle.r.runtime; +import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.DEFAULT_PACKAGES; + import java.io.BufferedReader; import java.io.File; import java.io.FileReader; @@ -31,7 +33,9 @@ import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.security.CodeSource; import java.util.HashMap; +import java.util.List; import java.util.Map; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -57,7 +61,13 @@ public final class REnvVars implements RContext.ContextState { @Override public RContext.ContextState initialize(RContext context) { // explicit environment settings in nested contexts must be installed first - checkExplciitEnvSettings(context); + checkExplicitEnvSettings(context); + RCmdOptions cmdOptions = context.getStartParams().getRCmdOptions(); + // If running Rscript, R_DEFAULT_PACKAGES may need to be set + String defaultPackages = cmdOptions.getString(DEFAULT_PACKAGES); + if (defaultPackages != null) { + envVars.put("R_DEFAULT_PACKAGES", defaultPackages); + } // set the standard vars defined by R checkRHome(); // Always read the system file @@ -119,7 +129,7 @@ public final class REnvVars implements RContext.ContextState { return new REnvVars(); } - private void checkExplciitEnvSettings(RContext context) { + private void checkExplicitEnvSettings(RContext context) { String[] envs = context.getEnvSettings(); if (envs == null || envs.length == 0) { return; @@ -152,10 +162,10 @@ public final class REnvVars implements RContext.ContextState { private static String rHome; /** - * Returns a file that only exists in a FastR {@code R_HOME}. + * Returns a file that serves to distinguish a FastR {@code R_HOME}. */ private static String markerFile() { - return "libjniboot." + (isMacOS() ? "dylib" : "so"); + return "Makeconf"; } /** @@ -181,6 +191,8 @@ public final class REnvVars implements RContext.ContextState { return rHome; } + private static CodeSource codeSource = REnvVars.class.getProtectionDomain().getCodeSource(); + /** * In the case where {@code R_HOME} is not set, which should only occur when FastR is invoked * from a {@link PolyglotEngine} created by another language, we try to locate the @@ -191,7 +203,7 @@ public final class REnvVars implements RContext.ContextState { * @return either a valid {@code R_HOME} or {@code null} */ private static Path getRHomePath() { - Path path = Paths.get(REnvVars.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getParent(); + Path path = Paths.get(codeSource.getLocation().getPath()).getParent(); String markerFile = markerFile(); while (path != null) { if (validateRHome(path, markerFile)) { @@ -205,12 +217,28 @@ public final class REnvVars implements RContext.ContextState { /** * Sanity check on the expected structure of an {@code R_HOME}. */ + @TruffleBoundary private static boolean validateRHome(Path path, String markerFile) { if (path == null) { return false; } - Path lib = path.resolve("lib"); - return Files.exists(lib) && Files.isDirectory(lib) && Files.exists(lib.resolve(markerFile)); + Path etc = path.resolve("etc"); + Path absMarkerFile = etc.resolve(markerFile); + return Files.exists(etc) && Files.isDirectory(etc) && Files.exists(absMarkerFile) && isFastR(absMarkerFile); + } + + private static boolean isFastR(Path makeconf) { + try { + List<String> lines = Files.readAllLines(makeconf); + for (String line : lines) { + if (line.startsWith("CFLAGS")) { + return line.contains("-DFASTR"); + } + } + } catch (IOException ex) { + throw RInternalError.shouldNotReachHere(); + } + return false; } private void checkRHome() { 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 da3597e88002595c1b56624f8bdbc740d118adca..fbb3953558a93d1e1a604db5ce01d7ce14dc455e 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 @@ -13,11 +13,14 @@ package com.oracle.truffle.r.runtime; import java.io.IOException; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import com.oracle.truffle.r.runtime.builtins.RBuiltinKind; import com.oracle.truffle.r.runtime.env.REnvironment.PutException; import com.oracle.truffle.r.runtime.nodes.RBaseNode; @@ -41,7 +44,6 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; * might require more information to disambiguate. Rather than create a new class to carry that, we * would simply create an instance of a {@link RBaseNode} subclass with the additional state. * Currently,there are no such cases. - * */ @SuppressWarnings("serial") public final class RError extends RuntimeException { @@ -68,32 +70,55 @@ public final class RError extends RuntimeException { } } + public abstract static class ErrorContext extends RBaseNode { + private ErrorContext() { + // private constructor + } + + @Override + protected RBaseNode getErrorContext() { + return this; + } + } + + private static final class ErrorContextImpl extends ErrorContext { + + } + + public static ErrorContext contextForBuiltin(RBuiltin builtin) { + ErrorContext callObj; + if (builtin == null) { + callObj = RError.NO_CALLER; + } else if (builtin.kind() == RBuiltinKind.INTERNAL) { + callObj = RError.SHOW_CALLER; + } else { + callObj = null; + } + return callObj; + } + /** * This flags a call to {@code error} or {@code warning} where the error message should show the * caller's caller. */ - public static final RBaseNode SHOW_CALLER2 = new RBaseNode() { - }; + public static final ErrorContext SHOW_CALLER2 = new ErrorContextImpl(); /** * This flags a call to {@code error} or {@code warning} where the error message should show the * caller of the current function. */ - public static final RBaseNode SHOW_CALLER = new RBaseNode() { - }; + public static final ErrorContext SHOW_CALLER = new ErrorContextImpl(); /** * A very special case that ensures that no caller is output in the error/warning message. This * is needed where, even if there is a caller, GnuR does not show it. */ - public static final RBaseNode NO_CALLER = new RBaseNode() { - }; + public static final ErrorContext NO_CALLER = new ErrorContextImpl(); /** * This is a workaround for a case in {@code RCallNode} where an error might be thrown while * executing a {@code RootNode}, which is not a subclass of {@link RBaseNode}. */ - public static final RBaseNode ROOTNODE = new RBaseNode() { - }; + public static final ErrorContext ROOTNODE = new ErrorContextImpl(); /** * TODO the string is not really needed as all output is performed prior to the throw. @@ -112,6 +137,19 @@ public final class RError extends RuntimeException { return verboseStackTrace; } + public static RError error(ErrorContext node, Message msg) { + throw error(node, msg, new Object[]{}); + } + + public static RError error(ErrorContext node, Message msg, Object arg) { + throw error(node, msg, new Object[]{arg}); + } + + @TruffleBoundary + public static RError error(ErrorContext node, Message msg, Object... args) { + throw error0(node, msg, args); + } + @TruffleBoundary public static RError error(RBaseNode node, Message msg, Object... args) { throw error0(node, msg, args); @@ -150,19 +188,18 @@ public final class RError extends RuntimeException { } current = current.getParent(); } - throw new AssertionError("Could not find RBaseNode for given Node. Is it not adopted in the AST?"); + throw RInternalError.shouldNotReachHere("Could not find RBaseNode for given Node. Is it not adopted in the AST?"); } /** * Handles an R error with the most general argument signature. All other facade variants * delegate to this method. * - * Note that the method never actually returns a result, but the throws the error directly. + * Note that the method never actually returns a result, instead it throws the error directly. * However, the signature has a return type of {@link RError} to allow callers to use the idiom * {@code throw error(...)} to indicate the control transfer. It is entirely possible that, due * to condition handlers, the error will not actually be thrown. * - * * @param node {@code RNode} of the code throwing the error, or {@link #SHOW_CALLER2} if not * available. If {@code NO_NODE} an attempt will be made to identify the call context * from the currently active frame. @@ -200,11 +237,17 @@ public final class RError extends RuntimeException { * A temporary error that indicates an unimplemented feature where terminating the VM using * {@link Utils#rSuicide(String)} would be inappropriate. */ - @TruffleBoundary public static RError nyi(RBaseNode node, String msg) { + CompilerDirectives.transferToInterpreter(); throw error(node, RError.Message.NYI, msg); } + @TruffleBoundary + public static void warning(ErrorContext node, Message msg, Object... args) { + assert node != null; + RErrorHandling.warningcall(true, node, msg, args); + } + @TruffleBoundary public static void warning(RBaseNode node, Message msg, Object... args) { assert node != null; @@ -221,7 +264,13 @@ public final class RError extends RuntimeException { @TruffleBoundary public static void performanceWarning(String string) { if (FastROptions.PerformanceWarnings.getBooleanValue()) { - warning(RError.SHOW_CALLER2, Message.PERFORMANCE, string); + System.out.println("Performance warning: " + string); + StackTraceElement[] trace = new RuntimeException().getStackTrace(); + for (int i = 1; i < trace.length && i < 8; i++) { + StackTraceElement element = trace[i]; + System.out.println(" at " + element.getClassName() + "." + element.getMethodName() + "(" + element.getFileName() + ":" + element.getLineNumber() + ")"); + } + // warning(RError.SHOW_CALLER2, Message.PERFORMANCE, string); } } @@ -268,9 +317,10 @@ public final class RError extends RuntimeException { NO_NONMISSING_MIN_NA("no non-missing arguments, returning NA"), LENGTH_NONNEGATIVE("length must be non-negative number"), MUST_BE_POSITIVE("'%s' must be a non-negative number"), + MUST_BE_POSITIVE_INT("'%s' must be a positive integer"), MUST_BE_POSITIVE_SD("%s must be non-negative number"), MUST_BE_SQUARE("'%s' (%d x %d) must be square"), - MUST_BE_SQUARE_COMPATIBLE("'%s' (%d x %d) must be compatible with '%' (%d x %d)"), + MUST_BE_SQUARE_COMPATIBLE("'%s' (%d x %d) must be compatible with '%s' (%d x %d)"), INVALID_TFB_SD("invalid (to - from)/by in seq(.)"), INVALID_TFB("invalid '(to - from)/by' in 'seq'"), WRONG_SIGN_IN_BY("wrong sign in 'by' argument"), @@ -300,6 +350,7 @@ public final class RError extends RuntimeException { NON_CHARACTER_NAMES("non-character names"), NON_NUMERIC_MATH("non-numeric argument to mathematical function"), NAN_PRODUCED("NaNs produced"), + NAN_PRODUCED_IN_FUNCTION("NaNs produced in function \"%s\""), NUMERIC_COMPLEX_MATRIX_VECTOR("requires numeric/complex matrix/vector arguments"), NON_CONFORMABLE_ARGS("non-conformable arguments"), DATA_VECTOR("'data' must be of a vector type"), @@ -333,10 +384,12 @@ public final class RError extends RuntimeException { CONN_XDR("cannot save XDR format to a text-mode connection"), ONLY_READ_BINARY_CONNECTION("can only read from a binary connection"), ONLY_WRITE_BINARY_CONNECTION("can only write to a binary connection"), + ONLY_WRITE_CHAR_OBJECTS("can only write character objects"), NOT_A_TEXT_CONNECTION("'con' is not a textConnection"), + NOT_AN_OUTPUT_TEXT_CONNECTION("'con' is not an output textConnection"), UNSEEKABLE_CONNECTION("'con' is not seekable"), MUST_BE_STRING_OR_CONNECTION("'%s' must be a character string or a connection"), - MORE_CHARACTERS("more characters requested than are in the string - will zero-pad"), + MORE_CHARACTERS("writeChar: more characters requested than are in the string - will zero-pad"), TOO_FEW_LINES_READ_LINES("too few lines read in readLineWRITE_ONs"), INVALID_CONNECTION("invalid connection"), OUT_OF_RANGE("out-of-range values treated as 0 in coercion to raw"), @@ -469,6 +522,7 @@ public final class RError extends RuntimeException { ATTRIBUTE_VECTOR_SAME_LENGTH("'%s' attribute [%d] must be the same length as the vector [%d]"), SCAN_UNEXPECTED("scan() expected '%s', got '%s'"), MUST_BE_ENVIRON("'%s' must be an environment"), + MUST_BE_ENVIRON2("%s must be an environment"), MUST_BE_INTEGER("'%s' must be an integer"), UNUSED_ARGUMENT("unused argument (%s)"), UNUSED_ARGUMENTS("unused arguments (%s)"), @@ -502,6 +556,7 @@ public final class RError extends RuntimeException { DIMS_GT_ZERO("'%s' must have dims > 0"), NOT_POSITIVE_DEFINITE("the leading minor of order %d is not positive definite"), LAPACK_INVALID_VALUE("argument %d of Lapack routine %s had invalid value"), + LAPACK_ZERO_INVERSE("element (%d, %d) is zero, so the inverse cannot be computed"), LAPACK_EXACTLY_SINGULAR("Lapack routine %s: system is exactly singular: U[%d,%d] = 0"), SYSTEM_COMP_SINGULAR("system is computationally singular: reciprocal condition number = %g"), RHS_SHOULD_HAVE_ROWS("right-hand side should have %d not %d rows"), @@ -533,6 +588,7 @@ public final class RError extends RuntimeException { USE_DEFUNCT("use of '%s' is defunct: use %s instead"), NCOL_ZERO("nc(0 for non-null data"), 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) : "), @@ -557,6 +613,7 @@ public final class RError extends RuntimeException { UNRECOGNIZED_FORMAT("unrecognized format specification '%s'"), 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"), // 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"), @@ -580,6 +637,7 @@ public final class RError extends RuntimeException { SUBSCRIPT_TYPES("incompatible types (from %s to %s) in [[ assignment"), INCOMPATIBLE_METHODS("incompatible methods (\"%s\", \"%s\") for \"%s\""), RECURSIVE_INDEXING_FAILED("recursive indexing failed at level %d"), + ARGUMENT_PASSED("%d argument passed to %s which requires %d"), ARGUMENTS_PASSED("%d arguments passed to %s which requires %d"), ARGUMENT_IGNORED("argument '%s' will be ignored"), NOT_CHARACTER_VECTOR("'%s' must be a character vector"), @@ -710,6 +768,7 @@ public final class RError extends RuntimeException { SLOT_NON_S4("trying to get slot \"%s\" from an object (class \"%s\") that is not an S4 object "), SLOT_CANNOT_GET("cannot get a slot (\"%s\") from an object of type \"%s\""), SLOT_NONE("no slot of name \"%s\" for this object of class \"%s\""), + SLOT_INVALID_TYPE_OR_LEN("invalid type or length for slot name"), S4OBJECT_NX_ENVIRONMENT("S4 object does not extend class \"environment\""), NOT_A_SLOT("'%s' is not a slot in class ”%s”"), NS_ALREADY_REG("namespace already registered"), @@ -767,6 +826,7 @@ public final class RError extends RuntimeException { INVALID_ARG_OF_LENGTH("invalid %s argument of length %d"), INVALID_ARG("invalid %s argument"), INVALID_FILENAME_PATTERN("invalid filename pattern"), + INVALID_FILENAME_SPECIFICATION("invalid filename specification"), INVALID_FILE_EXT("invalid file extension"), NO("no '%s'"), APPLIES_TO_VECTORS("%s applies only to vectors"), @@ -787,7 +847,37 @@ public final class RError extends RuntimeException { LOSS_OF_ACCURACY_MOD("probable complete loss of accuracy in modulus"), LENGTH_MISAPPLIED("LENGTH or similar applied to %s object"), TOO_MANY_ARGS("too many arguments"), - UNIMPLEMENTED_TYPE_IN_R("type \"%s\" unimplemented in R"); + UNIMPLEMENTED_TYPE_IN_R("type \"%s\" unimplemented in R"), + NOT_AN_OUTPUT_RAW_CONNECTION("'con' is not an output rawConnection"), + NOT_A_RAW_CONNECTION("'con' is not a rawConnection"), + SEEK_OUTSITE_RAW_CONNECTION("attempt to seek outside the range of the raw connection"), + VECTOR_IS_TOO_LARGE("vector is too large"), + SEEK_NOT_RELEVANT_FOR_TEXT_CON("seek is not relevant for text connection"), + NOT_ENABLED_FOR_THIS_CONN("'%s' not enabled for this connection"), + CANNOT_OPEN_FIFO("cannot open fifo '%s'"), + UNSUPPORTED_ENCODING_CONVERSION("unsupported conversion from '%s' to '%s'"), + UNABLE_TO_RESOLVE("unable to resolve '%s'"), + LINE_CONTAINS_EMBEDDED_NULLS("line %d appears to contain an embedded nul"), + UNSUPPORTED_URL_METHOD("method = \"%s\" is not supported"), + CANNOT_REPLICATE_NULL("cannot replicate NULL to a non-zero length"), + TRUNCATE_ONLY_WRITE_CONNECTION("can only truncate connections open for writing"), + TRUNCATE_ONLY_OPEN_CONN("can only truncate an open connection"), + TRUNCATE_NOT_ENABLED("truncation not enabled for this connection"), + TRUNCATE_UNSUPPORTED_FOR_CONN("cannot truncate connection: %s"), + INCOMPLETE_STRING_AT_EOF_DISCARDED("incomplete string at end of file has been discarded"), + INVALID_CHANNEL_OBJECT("invalid channel object (ByteChannel expected)"), + INVALID_TAG("invalid tag"), + INVALID_VARIABLE_NAMES("invalid variable names"), + INVALID_EXPRESSION("invalid expression in '%s'"), + INVALID_EXPRESSION_TYPE("expression must not be type '%s'"), + NOT_IN_DERIVATIVE_TABLE("Function '%s' is not in the derivatives table"), + CANNOT_ADD_BINDINGS("cannot add bindings to a locked environment"), + SYMBOL_HAS_REGULAR_BINDING("symbol already has a regular binding"), + CANNOT_CHANGE_LOCKED_ACTIVE_BINDING("cannot change active binding if binding is locked"), + NO_BINDING_FOR("no binding for \"%s\""), + INVALID_SUBSTRING_ARGS("invalid substring arguments"), + OBJECT_SIZE_ESTIMATE("The object size is only estimated."), + REPLACING_IN_NON_CHAR_OBJ("replacing substrings in a non-character object"); public final String message; final boolean hasArgs; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java index fb962d532743cc97d68c4e90fd3bb4e985d0abd7..ac0af78b884cfab4b846dbdea61cac73915befec 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java @@ -321,7 +321,7 @@ public class RErrorHandling { result.setClassAttr(RESTART_CLASS); } - public static Object invokeRestart(RList restart, Object args) { + public static void invokeRestart(RList restart, Object args) { ContextStateImpl errorHandlingState = getRErrorHandlingState(); Object exit = restartExit(restart); if (exit == RNull.instance) { @@ -338,7 +338,6 @@ public class RErrorHandling { } errorHandlingState.restartStack = pList.cdr(); } - return null; } } @@ -346,23 +345,26 @@ public class RErrorHandling { public static void signalCondition(RList cond, String msg, Object call) { ContextStateImpl errorHandlingState = getRErrorHandlingState(); Object oldStack = errorHandlingState.handlerStack; - RPairList pList; - while ((pList = findConditionHandler(cond)) != null) { - RList entry = (RList) pList.car(); - errorHandlingState.handlerStack = pList.cdr(); - if (isCallingEntry(entry)) { - Object h = entry.getDataAt(ENTRY_HANDLER); - if (h == RESTART_TOKEN) { - errorcallDfltWithCall(fromCall(call), Message.GENERIC, msg); + try { + RPairList pList; + while ((pList = findConditionHandler(cond)) != null) { + RList entry = (RList) pList.car(); + errorHandlingState.handlerStack = pList.cdr(); + if (isCallingEntry(entry)) { + Object h = entry.getDataAt(ENTRY_HANDLER); + if (h == RESTART_TOKEN) { + errorcallDfltWithCall(fromCall(call), Message.GENERIC, msg); + } else { + RFunction hf = (RFunction) h; + RContext.getEngine().evalFunction(hf, null, null, null, cond); + } } else { - RFunction hf = (RFunction) h; - RContext.getEngine().evalFunction(hf, null, null, null, cond); + throw gotoExitingHandler(cond, call, entry); } - } else { - throw gotoExitingHandler(cond, call, entry); } + } finally { + errorHandlingState.handlerStack = oldStack; } - errorHandlingState.handlerStack = oldStack; } /** @@ -374,24 +376,27 @@ public class RErrorHandling { String fMsg = formatMessage(msg, args); ContextStateImpl errorHandlingState = getRErrorHandlingState(); Object oldStack = errorHandlingState.handlerStack; - RPairList pList; - while ((pList = findSimpleErrorHandler()) != null) { - RList entry = (RList) pList.car(); - errorHandlingState.handlerStack = pList.cdr(); - errorHandlingState.errMsg = fMsg; - if (isCallingEntry(entry)) { - if (entry.getDataAt(ENTRY_HANDLER) == RESTART_TOKEN) { - return; + try { + RPairList pList; + while ((pList = findSimpleErrorHandler()) != null) { + RList entry = (RList) pList.car(); + errorHandlingState.handlerStack = pList.cdr(); + errorHandlingState.errMsg = fMsg; + if (isCallingEntry(entry)) { + if (entry.getDataAt(ENTRY_HANDLER) == RESTART_TOKEN) { + return; + } else { + RFunction handler = (RFunction) entry.getDataAt(2); + RStringVector errorMsgVec = RDataFactory.createStringVectorFromScalar(fMsg); + RContext.getRRuntimeASTAccess().callback(handler, new Object[]{errorMsgVec}); + } } else { - RFunction handler = (RFunction) entry.getDataAt(2); - RStringVector errorMsgVec = RDataFactory.createStringVectorFromScalar(fMsg); - RContext.getRRuntimeASTAccess().callback(handler, new Object[]{errorMsgVec, call}); + throw gotoExitingHandler(RNull.instance, call, entry); } - } else { - throw gotoExitingHandler(RNull.instance, call, entry); } + } finally { + errorHandlingState.handlerStack = oldStack; } - errorHandlingState.handlerStack = oldStack; } private static ReturnException gotoExitingHandler(Object cond, Object call, RList entry) throws ReturnException { @@ -420,7 +425,7 @@ public class RErrorHandling { private static RPairList findConditionHandler(RList cond) { // GnuR checks whether this is a string vector - in FastR it's statically typed to be - RStringVector classes = cond.getClassHierarchy(); + RAbstractStringVector classes = RContext.getRRuntimeASTAccess().getClassHierarchy(cond); Object list = getHandlerStack(); while (list != RNull.instance) { RPairList pList = (RPairList) list; @@ -592,7 +597,10 @@ public class RErrorHandling { */ ContextStateImpl errorHandlingState = getRErrorHandlingState(); RFunction f = errorHandlingState.getDotSignalSimpleWarning(); - RContext.getRRuntimeASTAccess().callback(f, new Object[]{warningMessage, call}); + if (f != null) { + RContext.getRRuntimeASTAccess().callback(f, new Object[]{warningMessage, call}); + } + // otherwise the subsystem is not initialized yet - no warning } private static void warningcallDfltWithCall(Object call, Message msg, Object... args) { @@ -672,26 +680,18 @@ public class RErrorHandling { if (warning.call == RNull.instance) { Utils.writeStderr(warning.message, true); } else { - String callSource = RContext.getRRuntimeASTAccess().getCallerSource((RLanguage) warning.call); - Utils.writeStderr(String.format("In %s : %s", callSource, warning.message), true); + printWarningMessage("In ", warning, 69); } } else if (nWarnings <= 10) { Utils.writeStderr("Warning messages:", true); for (int i = 0; i < nWarnings; i++) { - Object call = warnings.get(i).call; - String message = warnings.get(i).message; - if (call == RNull.instance || ((RLanguage) call).getRep().getSourceSection() == null) { + Warning warning = warnings.get(i); + if (warning.call == RNull.instance) { Utils.writeStderr((i + 1) + ":", true); - Utils.writeStderr(" " + warnings.get(i).message, true); + Utils.writeStderr(" " + warning.message, true); } else { - String callString = RContext.getRRuntimeASTAccess().getCallerSource((RLanguage) call); - // this can be enabled when deparsing is completely stable: - // callString = RDeparse.deparse1Line(call, false); - Utils.writeStderr((i + 1) + ": In ", false); - int firstLineLength = message.contains("\n") ? message.indexOf('\n') : message.length(); - boolean nl = callString.length() + firstLineLength > 65; - Utils.writeStderr(callString + " :", nl); - Utils.writeStderr((nl ? " " : " ") + message, true); + Utils.writeStderr(Integer.toString(i + 1), false); + printWarningMessage(": In ", warning, 65); } } } else { @@ -716,6 +716,20 @@ public class RErrorHandling { } } + private static void printWarningMessage(String prefix, Warning warning, int maxLen) { + String callString = RContext.getRRuntimeASTAccess().getCallerSource((RLanguage) warning.call); + + String message = warning.message; + int firstLineLength = message.contains("\n") ? message.indexOf('\n') : message.length(); + if (callString.length() + firstLineLength > maxLen) { + // split long lines + Utils.writeStderr(prefix + callString + " :", true); + Utils.writeStderr(" " + message, true); + } else { + Utils.writeStderr(prefix + callString + " : " + message, true); + } + } + public static void printDeferredWarnings() { if (getRErrorHandlingState().warnings.size() > 0) { Utils.writeStderr("In addition: ", false); @@ -735,7 +749,7 @@ public class RErrorHandling { // (is 74 a given percentage of console width?) if (preamble.length() + 1 + message.length() >= 74) { // +1 is for the extra space following the colon - return preamble + "\n " + message; + return preamble + " \n " + message; } else { return preamble + " " + message; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java index acd5193d5732cb56b231ee7a303c9bd8e5df8726..80a9f3cad82eed5af15ce628fe23d50d00074f97 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java @@ -28,6 +28,7 @@ import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Path; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.ffi.BaseRFFI; @@ -45,6 +46,7 @@ public final class RProfile implements RContext.ContextState { } @Override + @TruffleBoundary public RContext.ContextState initialize(RContext context) { String rHome = REnvVars.rHome(); FileSystem fileSystem = FileSystems.getDefault(); @@ -60,7 +62,7 @@ public final class RProfile implements RContext.ContextState { } File siteProfileFile = new File(siteProfilePath); if (siteProfileFile.exists()) { - newSiteProfile = getProfile(siteProfilePath); + newSiteProfile = getProfile(siteProfilePath, false); } } @@ -78,7 +80,7 @@ public final class RProfile implements RContext.ContextState { if (userProfilePath != null) { File userProfileFile = new File(userProfilePath); if (userProfileFile.exists()) { - newUserProfile = getProfile(userProfilePath); + newUserProfile = getProfile(userProfilePath, false); } } } @@ -92,7 +94,7 @@ public final class RProfile implements RContext.ContextState { public static Source systemProfile() { Path path = FileSystems.getDefault().getPath(REnvVars.rHome(), "library", "base", "R", "Rprofile"); - Source source = getProfile(path.toString()); + Source source = getProfile(path.toString(), true); if (source == null) { Utils.rSuicide("can't find system profile"); } @@ -107,9 +109,9 @@ public final class RProfile implements RContext.ContextState { return userProfile; } - private static Source getProfile(String path) { + private static Source getProfile(String path, boolean internal) { try { - return RSource.fromFileName(path); + return RSource.fromFileName(path, internal); } catch (IOException ex) { // GnuR does not report an error, just ignores return null; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java index fcda893df18d824b9e459a9126d9e80313560589..d80fe43d1b3578985e0c98a8257f844cbd4db456 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java @@ -11,6 +11,8 @@ */ package com.oracle.truffle.r.runtime; +import java.math.BigInteger; + import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; @@ -19,27 +21,34 @@ import com.oracle.truffle.api.frame.FrameSlotKind; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.TruffleObject; -import com.oracle.truffle.r.runtime.data.RAttributable; +import com.oracle.truffle.api.interop.java.JavaInterop; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDouble; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RInteger; +import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropByte; +import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropChar; +import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropFloat; +import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropLong; +import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropShort; import com.oracle.truffle.r.runtime.data.RLogical; +import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RRaw; import com.oracle.truffle.r.runtime.data.RString; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.RTypedValue; +import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; 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.RAbstractLogicalVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; -import java.math.BigInteger; public class RRuntime { @@ -47,7 +56,7 @@ public class RRuntime { // Parts of the welcome message originate from GNU R. public static final String WELCOME_MESSAGE = "FastR version " + RVersionNumber.FULL + "\n" + - "Copyright (c) 2013-16, Oracle and/or its affiliates\n" + + "Copyright (c) 2013-17, Oracle and/or its affiliates\n" + "Copyright (c) 1995-2016, The R Core Team\n" + "Copyright (c) 2016 The R Foundation for Statistical Computing\n" + "Copyright (c) 2012-4 Purdue University\n" + @@ -163,6 +172,8 @@ public class RRuntime { public static final String DOT_SIG_ARGS = ".SigArgs"; + public static final RSymbol DEFERRED_DEFAULT_MARKER = new RSymbol("__Deferred_Default_Marker__"); + public static final String R_TARGET = "target"; public static final String R_DOT_TARGET = ".target"; public static final String R_DEFINED = "defined"; @@ -191,6 +202,13 @@ public class RRuntime { } } + /** + * Create a {@link MaterializedFrame} for functions shared between different contexts. + */ + public static MaterializedFrame createNewFrame(FrameDescriptor frameDescriptor) { + return Truffle.getRuntime().createMaterializedFrame(RArguments.createUnitialized(), frameDescriptor); + } + /** * Create an {@link VirtualFrame} for a non-function environment, e.g., a package frame or the * global environment. @@ -202,10 +220,6 @@ public class RRuntime { return frame; } - public static RComplex createComplexNA() { - return RDataFactory.createComplex(COMPLEX_NA_REAL_PART, COMPLEX_NA_IMAGINARY_PART); - } - /** * Since a distinguished NaN value is used for NA, checking for {@code isNaN} suffices. */ @@ -276,6 +290,10 @@ public class RRuntime { return b == LOGICAL_TRUE; } + public static boolean fromLogical(byte b, boolean naReplacement) { + return naReplacement ? b != LOGICAL_FALSE : b == LOGICAL_TRUE; + } + // conversions from logical public static int logical2intNoCheck(byte value) { @@ -299,11 +317,11 @@ public class RRuntime { } public static RComplex logical2complex(byte value) { - return isNA(value) ? createComplexNA() : logical2complexNoCheck(value); + return isNA(value) ? RComplex.createNA() : logical2complexNoCheck(value); } public static String logicalToStringNoCheck(byte operand) { - assert operand == LOGICAL_TRUE || operand == LOGICAL_FALSE; + assert operand == LOGICAL_TRUE || operand == LOGICAL_FALSE : "operand: " + operand; return operand == LOGICAL_TRUE ? STRING_TRUE : STRING_FALSE; } @@ -477,14 +495,14 @@ public class RRuntime { return RDataFactory.createComplex(realPart * (negativeReal ? -1 : 1), imaginaryPart * (negativeImaginary ? -1 : 1)); } catch (NumberFormatException ex) { - return createComplexNA(); + return RComplex.createNA(); } } } @TruffleBoundary public static RComplex string2complex(String v) { - return isNA(v) ? createComplexNA() : string2complexNoCheck(v); + return isNA(v) ? RComplex.createNA() : string2complexNoCheck(v); } @TruffleBoundary @@ -519,7 +537,7 @@ public class RRuntime { } public static RComplex int2complex(int i) { - return isNA(i) ? createComplexNA() : int2complexNoCheck(i); + return isNA(i) ? RComplex.createNA() : int2complexNoCheck(i); } public static String intToStringNoCheck(int operand) { @@ -578,7 +596,7 @@ public class RRuntime { } public static RComplex double2complex(double d) { - return isNAorNaN(d) ? createComplexNA() : double2complexNoCheck(d); + return isNAorNaN(d) ? RComplex.createNA() : double2complexNoCheck(d); } public static int double2rawIntValue(double operand) { @@ -646,7 +664,6 @@ public class RRuntime { } else if (object instanceof Byte) { return logicalToString((byte) object); } - return String.valueOf(object); } @@ -672,12 +689,14 @@ public class RRuntime { } @TruffleBoundary - public static String quoteString(String value, boolean encodeNonASCII) { + public static String escapeString(String value, boolean encodeNonASCII, boolean quote) { if (isNA(value)) { return STRING_NA; } StringBuilder str = new StringBuilder(value.length() + 2); - str.append('\"'); + if (quote) { + str.append('\"'); + } int offset = 0; while (offset < value.length()) { int codepoint = value.codePointAt(offset); @@ -707,7 +726,11 @@ public class RRuntime { str.append("\\\\"); break; case '"': - str.append("\\\""); + if (quote) { + str.append("\\\""); + } else { + str.append('\"'); + } break; default: if (codepoint < 32 || codepoint == 0x7f) { @@ -727,7 +750,9 @@ public class RRuntime { } offset += Character.charCount(codepoint); } - str.append('\"'); + if (quote) { + str.append('\"'); + } return str.toString(); } @@ -810,15 +835,6 @@ public class RRuntime { } } - /** - * Returns {@code true} if the given object is R object and its class attribute contains given - * class. - */ - @TruffleBoundary - public static boolean hasRClass(Object obj, String rclassName) { - return obj instanceof RAttributable && ((RAttributable) obj).hasClass(rclassName); - } - public static boolean checkType(Object obj, RType type) { if (type == RType.Any) { return true; @@ -850,11 +866,6 @@ public class RRuntime { return RDataFactory.createLogicalVectorFromScalar((Byte) obj); } else if (obj instanceof String) { return RDataFactory.createStringVectorFromScalar((String) obj); - } else if (obj instanceof RComplex) { - RComplex complex = (RComplex) obj; - return RDataFactory.createComplexVector(new double[]{complex.getRealPart(), complex.getImaginaryPart()}, RDataFactory.COMPLETE_VECTOR); - } else if (obj instanceof RRaw) { - return RDataFactory.createRawVector(new byte[]{((RRaw) obj).getValue()}); } else { return obj; } @@ -915,4 +926,67 @@ public class RRuntime { private static boolean hasDims(RAbstractContainer xa) { return xa.hasDimensions(); } + + public static Object java2R(Object obj) { + if (obj == null) { + obj = RNull.instance; + } else if (obj instanceof Boolean) { + obj = RRuntime.asLogical((boolean) obj); + } else if (obj instanceof Byte) { + obj = ((Byte) obj).intValue(); + } else if (obj instanceof Short) { + obj = ((Short) obj).intValue(); + } else if (obj instanceof Long) { + obj = (((Long) obj).doubleValue()); + } else if (obj instanceof Float) { + obj = (((Float) obj).doubleValue()); + } else if (obj instanceof Character) { + obj = ((Character) obj).toString(); + } + return obj; + } + + public static Object[] r2Java(Object[] objects) { + Object[] ret = new Object[objects.length]; + for (int i = 0; i < objects.length; i++) { + ret[i] = RRuntime.r2Java(objects[i]); + } + return ret; + } + + public static Object r2Java(Object obj) { + if (obj == RNull.instance) { + return JavaInterop.asTruffleObject(null); + } else if (obj instanceof Byte) { + return RRuntime.fromLogical((byte) obj); + } else if (obj instanceof RInteropByte) { + return ((RInteropByte) obj).getValue(); + } else if (obj instanceof RInteropChar) { + return ((RInteropChar) obj).getValue(); + } else if (obj instanceof RInteropFloat) { + return ((RInteropFloat) obj).getValue(); + } else if (obj instanceof RInteropLong) { + return ((RInteropLong) obj).getValue(); + } else if (obj instanceof RInteropShort) { + return ((RInteropShort) obj).getValue(); + } else if (obj instanceof RAbstractAtomicVector && ((RAbstractAtomicVector) obj).getLength() == 1) { + if (obj instanceof RAbstractDoubleVector) { + RAbstractDoubleVector v = (RAbstractDoubleVector) obj; + return v.getDataAt(0); + } else if (obj instanceof RAbstractIntVector) { + RAbstractIntVector v = (RAbstractIntVector) obj; + return v.getDataAt(0); + } else if (obj instanceof RAbstractLogicalVector) { + RAbstractLogicalVector v = (RAbstractLogicalVector) obj; + return v.getDataAt(0) == RRuntime.LOGICAL_TRUE; + } else if (obj instanceof RAbstractRawVector) { + RAbstractRawVector v = (RAbstractRawVector) obj; + return v.getDataAt(0).getValue(); + } else if (obj instanceof RAbstractStringVector) { + RAbstractStringVector v = (RAbstractStringVector) obj; + return v.getDataAt(0); + } + } + return obj; + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java index 835b3d36e23b921d01ad2515f07ee8173188d363..15c84e15e28fe07d215ca5a9e60a6ff9f1b8d959 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.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 @@ -27,6 +27,7 @@ import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.r.runtime.context.Engine; import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RLanguage; @@ -35,6 +36,7 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @@ -201,4 +203,5 @@ public interface RRuntimeASTAccess { void checkDebugRequest(RFunction func); + RAbstractStringVector getClassHierarchy(RAttributable value); } 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 0c171118ede834f66f139028513543cb516212a5..eda8d1fee8af05be6eb5d8add2d77776f0b80202 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 @@ -33,6 +33,10 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; +import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.frame.FrameDescriptor; +import com.oracle.truffle.api.frame.FrameSlot; +import com.oracle.truffle.api.frame.FrameSlotKind; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.r.runtime.conn.RConnection; @@ -41,16 +45,13 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RAttributesLayout; import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RComplexVector; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.REmpty; import com.oracle.truffle.r.runtime.data.RExpression; import com.oracle.truffle.r.runtime.data.RExternalPtr; import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RLogicalVector; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPairList; @@ -74,6 +75,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.env.frame.ActiveBinding; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; @@ -118,6 +120,7 @@ public class RSerialize { static final int LEVELS_SHIFT = 12; static final int CACHED_MASK = 1 << 5; static final int HASHASH_MASK = 1; + static final int IS_ACTIVE_BINDING_MASK = 1 << 15; private Flags() { // prevent construction @@ -145,6 +148,10 @@ public class RSerialize { return (flagsValue & HAS_TAG_BIT_MASK) != 0; } + public static boolean isActiveBinding(int levs) { + return (levs & IS_ACTIVE_BINDING_MASK) != 0; + } + public static int packFlags(SEXPTYPE type, int gpbits, boolean isObj, boolean hasAttr, boolean hasTag) { int val = type.code; int levs = gpbits & (~(CACHED_MASK | HASHASH_MASK)); @@ -493,14 +500,13 @@ public class RSerialize { if (val == RNull.instance) { continue; } - RPairList pl = (RPairList) val; - env.safePut(((RSymbol) pl.getTag()).getName(), pl.car()); + safePutToEnv(env, (RPairList) val); } } } else { while (frame != RNull.instance) { RPairList pl = (RPairList) frame; - env.safePut(((RSymbol) pl.getTag()).getName(), pl.car()); + safePutToEnv(env, pl); frame = pl.cdr(); } } @@ -537,8 +543,14 @@ public class RSerialize { Object attrItem = RNull.instance; Object tagItem = RNull.instance; if (Flags.hasAttr(flags)) { + // create new language parsing context + int safedLangDepth = langDepth; + langDepth = 0; attrItem = readItem(); + // restore language parsing context + langDepth = safedLangDepth; + } if (Flags.hasTag(flags)) { tagItem = readItem(); @@ -625,6 +637,10 @@ public class RSerialize { } case LISTSXP: + if (Flags.isActiveBinding(levs)) { + assert carItem instanceof RFunction; + carItem = new ActiveBinding(RType.Any, (RFunction) carItem); + } RPairList pairList = RDataFactory.createPairList(carItem, cdrItem, tagItem, type); result = pairList; if (attrItem != RNull.instance) { @@ -832,6 +848,17 @@ public class RSerialize { return checkResult(result); } + private static void safePutToEnv(REnvironment env, RPairList pl) { + String name = ((RSymbol) pl.getTag()).getName(); + Object car = pl.car(); + if (ActiveBinding.isActiveBinding(car)) { + FrameSlot frameSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(env.getFrame().getFrameDescriptor(), name, FrameSlotKind.Object); + FrameSlotChangeMonitor.setActiveBinding(env.getFrame(), frameSlot, (ActiveBinding) car, false, null); + } else { + env.safePut(name, car); + } + } + private static Object checkResult(Object result) { assert result != null; return result; @@ -839,10 +866,7 @@ public class RSerialize { /** * GnuR uses a pairlist to represent attributes, whereas FastR uses the abstract RAttributes - * class. FastR also uses different types to represent data/frame and factor which is - * handled in the setClassAttr. N.B. In theory connections can be unserialized but they are - * unusable, so we don't go to the trouble of converting the {@link RIntVector} - * representation into an {@link RConnection}. + * class. */ @TruffleBoundary private static Object setAttributes(final Object object, Object attr) { @@ -1428,7 +1452,7 @@ public class RSerialize { */ String[] bindings = env.ls(true, null, false).getDataWithoutCopying(); for (String binding : bindings) { - Object value = env.get(binding); + Object value = getValueIgnoreActiveBinding(env.getFrame(), binding); writePairListEntry(binding, value); } terminatePairList(); @@ -1461,46 +1485,56 @@ public class RSerialize { stream.writeInt(1); writeCHARSXP((String) obj); } else { - outStringVec((RStringVector) obj, true); + outStringVec((RAbstractStringVector) obj, true); } break; } case INTSXP: { - RAbstractIntVector vec = (RAbstractIntVector) obj; - stream.writeInt(vec.getLength()); - for (int i = 0; i < vec.getLength(); i++) { - stream.writeInt(vec.getDataAt(i)); + if (obj instanceof Integer) { + stream.writeInt(1); + stream.writeInt((int) obj); + } else { + RAbstractIntVector vec = (RAbstractIntVector) obj; + stream.writeInt(vec.getLength()); + for (int i = 0; i < vec.getLength(); i++) { + stream.writeInt(vec.getDataAt(i)); + } } break; } case REALSXP: { - RAbstractDoubleVector vec = (RAbstractDoubleVector) obj; - stream.writeInt(vec.getLength()); - for (int i = 0; i < vec.getLength(); i++) { - stream.writeDouble(vec.getDataAt(i)); + if (obj instanceof Double) { + stream.writeInt(1); + stream.writeDouble((double) obj); + } else { + RAbstractDoubleVector vec = (RAbstractDoubleVector) obj; + stream.writeInt(vec.getLength()); + for (int i = 0; i < vec.getLength(); i++) { + stream.writeDouble(vec.getDataAt(i)); + } } break; } case LGLSXP: { // Output as ints - RLogicalVector vec = (RLogicalVector) obj; - stream.writeInt(vec.getLength()); - for (int i = 0; i < vec.getLength(); i++) { - byte val = vec.getDataAt(i); - if (RRuntime.isNA(val)) { - stream.writeInt(RRuntime.INT_NA); - } else { - stream.writeInt(vec.getDataAt(i)); + if (obj instanceof Byte) { + stream.writeInt(1); + stream.writeInt(RRuntime.logical2int((byte) obj)); + } else { + RAbstractLogicalVector vec = (RAbstractLogicalVector) obj; + stream.writeInt(vec.getLength()); + for (int i = 0; i < vec.getLength(); i++) { + stream.writeInt(RRuntime.logical2int(vec.getDataAt(i))); } } break; } case CPLXSXP: { - RComplexVector vec = (RComplexVector) obj; + RAbstractComplexVector vec = (RAbstractComplexVector) obj; stream.writeInt(vec.getLength()); for (int i = 0; i < vec.getLength(); i++) { RComplex val = vec.getDataAt(i); @@ -1551,55 +1585,6 @@ public class RSerialize { break; } - /* - * FastR scalar, (length 1) "vectors" - */ - - case FASTR_INT: { - Integer value = (Integer) obj; - stream.writeInt(1); - stream.writeInt(value); - break; - } - - case FASTR_DOUBLE: { - Double value = (Double) obj; - stream.writeInt(1); - stream.writeDouble(value); - break; - } - - case FASTR_BYTE: { - Byte value = (Byte) obj; - stream.writeInt(1); - if (RRuntime.isNA(value)) { - stream.writeInt(RRuntime.INT_NA); - } else { - stream.writeInt(value); - } - break; - } - - case FASTR_COMPLEX: { - RComplex value = (RComplex) obj; - stream.writeInt(1); - if (RRuntime.isNA(value)) { - stream.writeDouble(RRuntime.DOUBLE_NA); - stream.writeDouble(RRuntime.DOUBLE_NA); - } else { - stream.writeDouble(value.getRealPart()); - stream.writeDouble(value.getImaginaryPart()); - } - break; - } - - case FASTR_CONNECTION: { - RConnection con = (RConnection) obj; - stream.writeInt(1); - stream.writeInt(con.getDescriptor()); - break; - } - /* * The objects that GnuR represents as a pairlist. To avoid stack overflow, * these utilize manual tail recursion on the cdr of the pairlist. @@ -1700,6 +1685,16 @@ public class RSerialize { } while (tailCall); } + private static Object getValueIgnoreActiveBinding(Frame frame, String key) { + FrameDescriptor fd = frame.getFrameDescriptor(); + FrameSlot slot = fd.findFrameSlot(key); + if (slot == null) { + return null; + } else { + return frame.getValue(slot); + } + } + private Object getPersistentName(Object obj) { if (hook == null) { return RNull.instance; @@ -1725,7 +1720,7 @@ public class RSerialize { return result; } - private void outStringVec(RStringVector vec, boolean strsxp) throws IOException { + private void outStringVec(RAbstractStringVector vec, boolean strsxp) throws IOException { if (!strsxp) { stream.writeInt(0); } @@ -1773,7 +1768,8 @@ public class RSerialize { } private void writePairListEntry(String name, Object value) throws IOException { - stream.writeInt(Flags.packFlags(SEXPTYPE.LISTSXP, 0, false, false, true)); + boolean isActiveBinding = ActiveBinding.isActiveBinding(value); + stream.writeInt(Flags.packFlags(SEXPTYPE.LISTSXP, isActiveBinding ? Flags.IS_ACTIVE_BINDING_MASK : 0, false, false, true)); RSymbol sym = state.findSymbol(name); int refIndex; if ((refIndex = getRefIndex(sym)) != -1) { @@ -1781,7 +1777,11 @@ public class RSerialize { } else { writeSymbol(sym); } - writeItem(value); + if (isActiveBinding) { + writeItem(((ActiveBinding) value).getFunction()); + } else { + writeItem(value); + } } private void writeSymbol(RSymbol name) throws IOException { 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 31938c37b52c0ee0b9047c16445fbaa20d0d594d..e1ef2d2fc9afa9196652aa5e6cec3fb6600fdc12 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 @@ -90,10 +90,14 @@ public class RSource { * Create an (external) source from the {@code text} that is known to originate from the file * system path {@code path}. The simulates the behavior of {@link #fromFile}. */ - public static Source fromFileName(String text, String path) throws URISyntaxException { + public static Source fromFileName(String text, String path, boolean internal) throws URISyntaxException { File file = new File(path).getAbsoluteFile(); URI uri = new URI("file://" + file.getAbsolutePath()); - return Source.newBuilder(text).name(file.getName()).uri(uri).mimeType(RRuntime.R_APP_MIME).build(); + Source.Builder<RuntimeException, RuntimeException, RuntimeException> builder = Source.newBuilder(text).name(file.getName()).uri(uri).mimeType(RRuntime.R_APP_MIME); + if (internal) { + builder.internal(); + } + return builder.build(); } /** @@ -103,6 +107,13 @@ public class RSource { return fromTextInternal(text, description, RRuntime.R_APP_MIME); } + /** + * Create an {@code internal} source from {@code text} and {@code description}. + */ + public static Source fromTextInternalInvisible(String text, Internal description) { + return fromTextInternalInvisible(text, description, RRuntime.R_APP_MIME); + } + /** * Create an {@code internal} source from {@code text} and {@code description} of given * {@code mimeType}. @@ -112,6 +123,15 @@ public class RSource { return Source.newBuilder(text).name(description.string).mimeType(mimeType).internal().interactive().build(); } + /** + * Create an {@code internal} source from {@code text} and {@code description} of given + * {@code mimeType}. + */ + + public static Source fromTextInternalInvisible(String text, Internal description, String mimeType) { + return Source.newBuilder(text).name(description.string).mimeType(mimeType).internal().build(); + } + /** * Create an {@code internal} source for a deparsed package from {@code text} and * {@code packageName}. @@ -137,8 +157,12 @@ public class RSource { /** * Create an (external) source from the file system path {@code path}. */ - public static Source fromFileName(String path) throws IOException { - return Source.newBuilder(new File(path)).name(path).mimeType(RRuntime.R_APP_MIME).build(); + public static Source fromFileName(String path, boolean internal) throws IOException { + Source.Builder<IOException, RuntimeException, RuntimeException> builder = Source.newBuilder(new File(path)).name(path).mimeType(RRuntime.R_APP_MIME); + if (internal) { + builder.internal(); + } + return builder.build(); } /** @@ -148,6 +172,13 @@ public class RSource { return Source.newBuilder(file).name(file.getName()).mimeType(RRuntime.R_APP_MIME).build(); } + /** + * Create a source from the file system path denoted by {@code file}. + */ + public static Source fromTempFile(File file) throws IOException { + return Source.newBuilder(file).name(file.getName()).mimeType(RRuntime.R_APP_MIME).internal().build(); + } + /** * Create an (external) source from {@code url}. */ diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RStartParams.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RStartParams.java index 854b3c93b6bd5580f61f6084f1ae8fe534c4d490..cdadca6a121452237e13e3aa3eb0059b9ac7c9d6 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RStartParams.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RStartParams.java @@ -86,9 +86,9 @@ public class RStartParams { private boolean noReadline; /** - * The original command line arguments that were parsed by {@link RCmdOptions}. + * The result from parsing the command line options. */ - private final String[] arguments; + private final RCmdOptions cmdOptions; /** * Indicates that FastR is running embedded. @@ -96,7 +96,7 @@ public class RStartParams { private boolean embedded; public RStartParams(RCmdOptions options, boolean embedded) { - this.arguments = options.getArguments(); + this.cmdOptions = options; this.embedded = embedded; if (options.getBoolean(VERBOSE)) { this.verbose = true; @@ -246,8 +246,12 @@ public class RStartParams { return this.noReadline; } + public RCmdOptions getRCmdOptions() { + return cmdOptions; + } + public String[] getArguments() { - return arguments; + return cmdOptions.getArguments(); } public void setEmbedded() { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java index 21a0d9b77a7c50ebbcb146afdc853e096509ce1f..aa4108bd0360cd282c4e4cc2b35a642c0a56bba0 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -87,9 +87,11 @@ public class RSubstitute { * <li>..., replace by contents of ... (if bound)</li> * </ul> */ - private static <T> T substitute(RCodeBuilder<T> builder, RSyntaxElement original, REnvironment env) { + private static <T> T substitute(RCodeBuilder<T> builder, RSyntaxElement original, REnvironment callEnv) { return new RSyntaxVisitor<T>() { + REnvironment env = callEnv; + @Override protected T visit(RSyntaxCall element) { RSyntaxElement lhs = element.getSyntaxLHS(); @@ -134,8 +136,19 @@ public class RSubstitute { } RArgsValuesAndNames dots = (RArgsValuesAndNames) substitute; for (int j = 0; j < dots.getLength(); j++) { - RSyntaxElement contents = substituteElement(dots.getArgument(j)); - args.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, dots.getSignature().getName(j), accept(contents))); + Object dotArg = dots.getArgument(j); + RSyntaxElement contents = substituteElement(dotArg); + if (dotArg instanceof RPromise) { + // Replace the environment used to substitute symbols in a + // promise by the empty one to prevent an infinite recursion + // if the promise contains a vararg + REnvironment origEnv = env; + env = REnvironment.emptyEnv(); + args.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, dots.getSignature().getName(j), accept(contents))); + env = origEnv; + } else { + args.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, dots.getSignature().getName(j), accept(contents))); + } } continue; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java index 9ee98c9d78bcde430d2e58bc088703ab50ada1bf..c4d03652bf2589339d29122b77bc67cd6709bc7d 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java @@ -5,7 +5,7 @@ * * Copyright (c) 1995-2012, The R Core Team * Copyright (c) 2003, The R Foundation - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -33,20 +33,26 @@ public enum RType { Function("function", -1), Matrix("matrix", -1), Array("array", -1), - Closure("closure", -1), - Builtin("builtin", -1), - Special("special", -1), - Symbol("symbol", -1), + Closure("closure", "function", -1), + Builtin("builtin", "function", -1), + Special("special", "function", -1), + Symbol("symbol", "name", -1), Environment("environment", -1), PairList("pairlist", -1), - Language("language", -1), + Language("language", "call", -1), Promise("promise", -1), DefunctReal("real", -1), DefunctSingle("single", -1), ExternalPtr("externalptr", -1), S4Object("S4", -1), Connection("connection", -1), - Dots("...", -1); + Dots("...", -1), + TruffleObject("truffle.object", -1), + RInteropByte("interopt.byte", -1), + RInteropChar("interopt.char", -1), + RInteropFloat("interopt.float", -1), + RInteropLong("interopt.long", -1), + RInteropShort("interopt.short", -1); public static final int NO_PRECEDENCE = -1; public static final int NUMBER_OF_PRECEDENCES = 9; @@ -98,6 +104,7 @@ public enum RType { case Character: case Raw: case List: + case Expression: return true; default: return false; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ResourceHandlerFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ResourceHandlerFactory.java index b20589fd8459804332cbe644af1209bdca750a7c..f785535b8eb13581f3a81a38210827688cb6819e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ResourceHandlerFactory.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ResourceHandlerFactory.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 @@ -53,7 +53,14 @@ public abstract class ResourceHandlerFactory { } static { - final String prop = System.getProperty("fastr.resource.factory.class", "com.oracle.truffle.r.runtime.DefaultResourceHandlerFactory"); + String prop = System.getProperty("fastr.resource.factory.class"); + if (prop == null) { + if (FastRConfig.ManagedMode) { + prop = "com.oracle.truffle.r.nodes.builtin.EagerResourceHandlerFactory"; + } else { + prop = LazyResourceHandlerFactory.class.getName(); + } + } try { theInstance = (ResourceHandlerFactory) Class.forName(prop).newInstance(); } catch (Exception ex) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java index d0783f13cffee5b279ee86f5b0d07b9da968cd97..822fd6f26e4052502405b6e19ed7b208469034ce 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java @@ -23,8 +23,14 @@ package com.oracle.truffle.r.runtime; import java.io.File; +import java.io.IOException; import java.nio.file.FileSystems; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; import java.util.Random; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -47,17 +53,12 @@ public class TempPathName implements RContext.ContextState { @Override public RContext.ContextState initialize(RContext context) { - final String[] envVars = new String[]{"TMPDIR", "TMP", "TEMP"}; - String startingTempDir = null; - for (String envVar : envVars) { - String value = System.getenv(envVar); - if (value != null && isWriteableDirectory(value)) { - startingTempDir = value; - } - } - if (startingTempDir == null) { - startingTempDir = "/tmp"; + if (context.getKind() == RContext.ContextKind.SHARE_PARENT_RW) { + // share tempdir with parent + tempDirPath = context.getParent().stateTempPath.tempDirPath; + return this; } + String startingTempDir = Utils.getUserTempDir(); Path startingTempDirPath = FileSystems.getDefault().getPath(startingTempDir, "Rtmp"); // ensure absolute, to avoid problems with R code does a setwd if (!startingTempDirPath.isAbsolute()) { @@ -72,13 +73,22 @@ public class TempPathName implements RContext.ContextState { return this; } - private static boolean isWriteableDirectory(String path) { - File f = new File(path); - return f.exists() && f.isDirectory() && f.canWrite(); + @Override + @TruffleBoundary + public void beforeDestroy(RContext context) { + if (context.getKind() == RContext.ContextKind.SHARE_PARENT_RW) { + return; + } + try { + Files.walkFileTree(Paths.get(tempDirPath), new DeleteVisitor()); + } catch (Throwable e) { + // unexpected and we are exiting anyway + } } public static String tempDirPath() { - return RContext.getInstance().stateTempPath.tempDirPath; + String result = RContext.getInstance().stateTempPath.tempDirPath; + return result; } public static TempPathName newContextState() { @@ -107,4 +117,22 @@ public class TempPathName implements RContext.ContextState { sb.append(RANDOM_CHARACTERS.charAt(rand.nextInt(RANDOM_CHARACTERS_LENGTH))); } } + + private static final class DeleteVisitor extends SimpleFileVisitor<Path> { + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + return del(file); + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + return del(dir); + } + + private static FileVisitResult del(Path p) throws IOException { + Files.delete(p); + return FileVisitResult.CONTINUE; + } + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java index 19bb59be1350811d3a3a9589b789120af257b0a2..a511ed968943b46d2c5da96149c8453114209c04 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java @@ -23,6 +23,7 @@ package com.oracle.truffle.r.runtime; import java.io.BufferedReader; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -60,6 +61,7 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPairList; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.MultiSlotData; import com.oracle.truffle.r.runtime.ffi.BaseRFFI; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @@ -362,6 +364,7 @@ public final class Utils { */ @TruffleBoundary public static Frame getStackFrame(FrameAccess fa, RCaller target) { + RError.performanceWarning("slow frame access - getStackFrame1"); assert target != null; return Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<Frame>() { boolean first = true; @@ -388,6 +391,7 @@ public final class Utils { */ @TruffleBoundary public static Frame getStackFrame(FrameAccess fa, int depth) { + RError.performanceWarning("slow frame access - getStackFrame2"); return Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<Frame>() { boolean first = true; @@ -418,6 +422,7 @@ public final class Utils { */ @TruffleBoundary public static <T> T iterateRFrames(FrameAccess fa, Function<Frame, T> func) { + RError.performanceWarning("slow frame access - iterateRFrames"); return Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<T>() { boolean first = true; @@ -463,6 +468,7 @@ public final class Utils { */ @TruffleBoundary public static Frame getActualCurrentFrame() { + RError.performanceWarning("slow frame access - getActualCurrentFrame"); FrameInstance frameInstance = Truffle.getRuntime().getCurrentFrame(); if (frameInstance == null) { // Might be the case during initialization, when envs are prepared before the actual @@ -528,6 +534,7 @@ public final class Utils { */ @TruffleBoundary public static Object createTraceback(int skip) { + RError.performanceWarning("slow frame access - createTraceback"); FrameInstance current = Truffle.getRuntime().getCurrentFrame(); if (current != null) { TracebackVisitor fiv = new TracebackVisitor(skip); @@ -543,6 +550,7 @@ public final class Utils { */ @TruffleBoundary public static String createStackTrace(boolean printFrameSlots) { + RError.performanceWarning("slow frame access - createStackTrace"); FrameInstance current = Truffle.getRuntime().getCurrentFrame(); if (current == null) { return "no R stack trace available\n"; @@ -565,6 +573,7 @@ public final class Utils { } private static void dumpFrame(StringBuilder str, CallTarget callTarget, Frame frame, boolean printFrameSlots, boolean isVirtual) { + CompilerAsserts.neverPartOfCompilation(); try { CompilerAsserts.neverPartOfCompilation(); if (str.length() > 0) { @@ -593,12 +602,9 @@ public final class Utils { FrameDescriptor frameDescriptor = unwrapped.getFrameDescriptor(); for (FrameSlot s : frameDescriptor.getSlots()) { str.append("\n ").append(s.getIdentifier()).append(" = "); - Object value; - try { - value = unwrapped.getValue(s); - } catch (Throwable t) { - str.append("<exception ").append(t.getClass().getSimpleName()).append(" while acquiring slot ").append(s.getIdentifier()).append(">"); - continue; + Object value = unwrapped.getValue(s); + if (value instanceof MultiSlotData) { + value = ((MultiSlotData) value).get(RContext.getInstance().getMultiSlotInd()); } try { if (value instanceof RAbstractContainer && ((RAbstractContainer) value).getLength() > 32) { @@ -692,4 +698,24 @@ public final class Utils { public static String stringFormat(String format, Object... objects) { return String.format(format, objects); } + + private static boolean isWriteableDirectory(String path) { + File f = new File(path); + return f.exists() && f.isDirectory() && f.canWrite(); + } + + public static String getUserTempDir() { + final String[] envVars = new String[]{"TMPDIR", "TMP", "TEMP"}; + String startingTempDir = null; + for (String envVar : envVars) { + String value = System.getenv(envVar); + if (value != null && isWriteableDirectory(value)) { + startingTempDir = value; + } + } + if (startingTempDir == null) { + startingTempDir = "/tmp"; + } + return startingTempDir; + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinDescriptor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinDescriptor.java index ff436f3fb01b8f02edcae346ce7fe2b386671113..5ca12b5a0433fecc93d33bcee65e9fd0de6094b8 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinDescriptor.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinDescriptor.java @@ -108,10 +108,6 @@ public abstract class RBuiltinDescriptor { return signature; } - public int[] getNonEvalArgs() { - return nonEvalArgs; - } - public boolean isAlwaysSplit() { return alwaysSplit; } @@ -147,4 +143,10 @@ public abstract class RBuiltinDescriptor { public RSpecialFactory getSpecialCall() { return specialCall; } + + @Override + public String toString() { + return "RBuiltinFactory [name=" + getName() + ", aliases=" + Arrays.toString(getAliases()) + ", kind=" + getKind() + ", siagnature=" + getSignature() + ", nonEvaledArgs=" + + Arrays.toString(nonEvalArgs) + ", splitCaller=" + isSplitCaller() + ", dispatch=" + getDispatch() + ", behavior=" + getBehavior() + "]"; + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ChannelConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ChannelConnections.java new file mode 100644 index 0000000000000000000000000000000000000000..f5d8cd180262a621df563f2311e3ece0121fca12 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ChannelConnections.java @@ -0,0 +1,96 @@ +/* + * 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 + * 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.runtime.conn; + +import java.io.IOException; +import java.nio.channels.ByteChannel; +import java.util.Objects; + +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass; + +/** + * A connection type for communicating to arbitrary Java NIO channels. + */ +public class ChannelConnections { + + public static class ChannelRConnection extends BaseRConnection { + + private final String description; + private final ByteChannel channel; + + public ChannelRConnection(String description, ByteChannel channel, String modeString, String encoding) throws IOException { + super(ConnectionClass.CHANNEL, modeString, AbstractOpenMode.Read, encoding); + this.description = description; + this.channel = Objects.requireNonNull(channel); + openNonLazyConnection(); + } + + @Override + protected void createDelegateConnection() throws IOException { + final AbstractOpenMode mode = getOpenMode().abstractOpenMode; + switch (mode) { + case Read: + case ReadBinary: + case Write: + case WriteBinary: + case ReadWrite: + case ReadWriteBinary: + setDelegate(new ChannelReadWriteRConnection(this)); + break; + default: + throw RError.nyi(RError.SHOW_CALLER, mode.name()); + } + } + + @Override + public String getSummaryDescription() { + return description; + } + + } + + private static class ChannelReadWriteRConnection extends DelegateReadWriteRConnection { + + private final ChannelRConnection base; + + protected ChannelReadWriteRConnection(ChannelRConnection base) { + super(base, 0); + this.base = base; + } + + @Override + public ByteChannel getChannel() throws IOException { + return base.channel; + } + + @Override + public boolean isSeekable() { + return false; + } + + } + +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/CompressedConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/CompressedConnections.java deleted file mode 100644 index 7bf6d1af13b9fb97d677e675c67c74b63b24618f..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/CompressedConnections.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * 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 - * 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.runtime.conn; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; - -import org.tukaani.xz.LZMA2Options; -import org.tukaani.xz.XZ; -import org.tukaani.xz.XZInputStream; -import org.tukaani.xz.XZOutputStream; - -import com.oracle.truffle.r.runtime.RCompression; -import com.oracle.truffle.r.runtime.RCompression.Type; -import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BasePathRConnection; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadRConnection; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateWriteRConnection; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ReadWriteHelper; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; - -public class CompressedConnections { - public static final int GZIP_BUFFER_SIZE = (2 << 20); - - /** - * Base class for all modes of gzfile/bzfile/xzfile connections. N.B. In GNU R these can read - * gzip, bzip, lzma and uncompressed files, and this has to be implemented by reading the first - * few bytes of the file and detecting the type of the file. - */ - public static class CompressedRConnection extends BasePathRConnection { - private final RCompression.Type cType; - @SuppressWarnings("unused") private final String encoding; // TODO - @SuppressWarnings("unused") private final int compression; // TODO - - public CompressedRConnection(String path, String modeString, Type cType, String encoding, int compression) throws IOException { - super(path, mapConnectionClass(cType), modeString, AbstractOpenMode.ReadBinary); - this.cType = cType; - this.encoding = encoding; - this.compression = compression; - openNonLazyConnection(); - } - - private static ConnectionClass mapConnectionClass(RCompression.Type cType) { - switch (cType) { - case NONE: - return ConnectionClass.File; - case GZIP: - return ConnectionClass.GZFile; - case BZIP2: - return ConnectionClass.BZFile; - case XZ: - return ConnectionClass.XZFile; - default: - throw RInternalError.shouldNotReachHere(); - } - } - - @Override - protected void createDelegateConnection() throws IOException { - DelegateRConnection delegate = null; - AbstractOpenMode openMode = getOpenMode().abstractOpenMode; - switch (openMode) { - case Read: - case ReadBinary: - /* - * For input, we check the actual compression type as GNU R is permissive about - * the claimed type. - */ - RCompression.Type cTypeActual = RCompression.getCompressionType(path); - if (cTypeActual != cType) { - updateConnectionClass(mapConnectionClass(cTypeActual)); - } - switch (cTypeActual) { - case NONE: - if (openMode == AbstractOpenMode.ReadBinary) { - delegate = new FileConnections.FileReadBinaryRConnection(this); - } else { - delegate = new FileConnections.FileReadTextRConnection(this); - } - break; - case GZIP: - delegate = new CompressedInputRConnection(this, new GZIPInputStream(new FileInputStream(path), GZIP_BUFFER_SIZE)); - break; - case XZ: - delegate = new CompressedInputRConnection(this, new XZInputStream(new FileInputStream(path))); - break; - case BZIP2: - // no in Java support, so go via byte array - byte[] bzipUdata = RCompression.bzipUncompressFromFile(path); - delegate = new ByteStreamCompressedInputRConnection(this, new ByteArrayInputStream(bzipUdata)); - } - break; - - case Append: - case AppendBinary: - case Write: - case WriteBinary: { - boolean append = openMode == AbstractOpenMode.Append || openMode == AbstractOpenMode.AppendBinary; - switch (cType) { - case GZIP: - delegate = new CompressedOutputRConnection(this, new GZIPOutputStream(new FileOutputStream(path, append), GZIP_BUFFER_SIZE)); - break; - case BZIP2: - delegate = new BZip2OutputRConnection(this, new ByteArrayOutputStream(), append); - break; - case XZ: - delegate = new CompressedOutputRConnection(this, new XZOutputStream(new FileOutputStream(path, append), new LZMA2Options(), XZ.CHECK_CRC32)); - break; - } - break; - } - default: - throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + getOpenMode()); - } - setDelegate(delegate); - } - - // @Override - /** - * GnuR behavior for lazy connections is odd, e.g. gzfile returns "text", even though the - * default mode is "rb". - */ - // public boolean isTextMode() { - // } - } - - private static class CompressedInputRConnection extends DelegateReadRConnection implements ReadWriteHelper { - private final InputStream inputStream; - - protected CompressedInputRConnection(CompressedRConnection base, InputStream is) { - super(base); - this.inputStream = is; - } - - @Override - public String readChar(int nchars, boolean useBytes) throws IOException { - return readCharHelper(nchars, inputStream, useBytes); - } - - @Override - public int readBin(ByteBuffer buffer) throws IOException { - return readBinHelper(buffer, inputStream); - } - - @Override - public byte[] readBinChars() throws IOException { - return readBinCharsHelper(inputStream); - } - - @Override - public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException { - return readLinesHelper(inputStream, n, warn, skipNul); - } - - @Override - public InputStream getInputStream() throws IOException { - return inputStream; - } - - @Override - public void closeAndDestroy() throws IOException { - base.closed = true; - close(); - } - - @Override - public void close() throws IOException { - inputStream.close(); - } - } - - private static class ByteStreamCompressedInputRConnection extends CompressedInputRConnection { - ByteStreamCompressedInputRConnection(CompressedRConnection base, ByteArrayInputStream is) { - super(base, is); - } - } - - private static class CompressedOutputRConnection extends DelegateWriteRConnection implements ReadWriteHelper { - protected OutputStream outputStream; - - protected CompressedOutputRConnection(CompressedRConnection base, OutputStream os) { - super(base); - this.outputStream = os; - } - - @Override - public OutputStream getOutputStream() throws IOException { - return outputStream; - } - - @Override - public void closeAndDestroy() throws IOException { - base.closed = true; - close(); - } - - @Override - public void close() throws IOException { - flush(); - outputStream.close(); - } - - @Override - public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException { - writeLinesHelper(outputStream, lines, sep); - } - - @Override - public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException { - writeCharHelper(outputStream, s, pad, eos); - } - - @Override - public void writeBin(ByteBuffer buffer) throws IOException { - writeBinHelper(buffer, outputStream); - } - - @Override - public void writeString(String s, boolean nl) throws IOException { - writeStringHelper(outputStream, s, nl); - } - - @Override - public void flush() throws IOException { - outputStream.flush(); - } - } - - private static class BZip2OutputRConnection extends CompressedOutputRConnection { - private final ByteArrayOutputStream bos; - private final boolean append; - - BZip2OutputRConnection(CompressedRConnection base, ByteArrayOutputStream os, boolean append) { - super(base, os); - this.bos = os; - this.append = append; - } - - @Override - public void close() throws IOException { - flush(); - outputStream.close(); - // Now actually do the compression using sub-process - byte[] data = bos.toByteArray(); - RCompression.bzipCompressToFile(data, ((BasePathRConnection) base).path, append); - } - } -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java index 2d00f37c27ddb2dbc508ce613d16692e333d038a..825aa4cd44c3b1b801426d9b470d9da99b8ba979 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java @@ -22,7 +22,6 @@ */ package com.oracle.truffle.r.runtime.conn; -import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -30,15 +29,29 @@ import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.nio.ByteBuffer; +import java.nio.channels.ByteChannel; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.object.DynamicObject; 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.Utils; import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RAttributesLayout; import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RExternalPtr; +import com.oracle.truffle.r.runtime.data.RNull; +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; @@ -107,7 +120,7 @@ public class ConnectionSupport { for (int i = 0; i <= hwm; i++) { WeakReference<BaseRConnection> ref = allConnections.get(i); if (ref != null) { - BaseRConnection con = ref.get(); + RConnection con = ref.get(); if (con != null) { list.add(i); } @@ -302,6 +315,11 @@ public class ConnectionSupport { */ return modeString; } + + @Override + public String toString() { + return modeString; + } } public enum ConnectionClass { @@ -313,7 +331,13 @@ public class ConnectionSupport { Socket("sockconn"), Text("textConnection"), URL("url"), - Internal("internal"); + RAW("rawConnection"), + Internal("internal"), + PIPE("pipe"), + FIFO("fifo"), + CHANNEL("Java Channel"), + NATIVE("custom"), + INVALID("invalid"); private final String printName; @@ -336,19 +360,16 @@ public class ConnectionSupport { } } - // TODO implement all open modes + public static final class InvalidConnection extends BaseRConnection { - public static final class InvalidConnection extends RConnection { + protected InvalidConnection() { + super(ConnectionClass.INVALID, null); + } public static final InvalidConnection instance = new InvalidConnection(); private static final int INVALID_DESCRIPTOR = -1; - @Override - public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException { - throw RInternalError.shouldNotReachHere("INVALID CONNECTION"); - } - @Override public String[] readLines(int n, boolean warn, boolean skipNul) throws IOException { throw RInternalError.shouldNotReachHere("INVALID CONNECTION"); @@ -380,7 +401,7 @@ public class ConnectionSupport { } @Override - public RConnection forceOpen(String modeString) throws IOException { + public BaseRConnection forceOpen(String modeString) throws IOException { throw RInternalError.shouldNotReachHere("INVALID CONNECTION"); } @@ -394,11 +415,6 @@ public class ConnectionSupport { throw RInternalError.shouldNotReachHere("INVALID CONNECTION"); } - @Override - public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { - throw RInternalError.shouldNotReachHere("INVALID CONNECTION"); - } - @Override public int getc() throws IOException { throw RInternalError.shouldNotReachHere("INVALID CONNECTION"); @@ -458,6 +474,31 @@ public class ConnectionSupport { public boolean isOpen() { throw RInternalError.shouldNotReachHere("INVALID CONNECTION"); } + + @Override + public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { + throw RInternalError.shouldNotReachHere("INVALID CONNECTION"); + } + + @Override + public ByteChannel getChannel() throws IOException { + throw RInternalError.shouldNotReachHere("INVALID CONNECTION"); + } + + @Override + public void truncate() throws IOException { + throw RInternalError.shouldNotReachHere("INVALID CONNECTION"); + } + + @Override + protected void createDelegateConnection() throws IOException { + throw RInternalError.shouldNotReachHere("INVALID CONNECTION"); + } + + @Override + public String getSummaryDescription() { + throw RInternalError.shouldNotReachHere("INVALID CONNECTION"); + } } /** @@ -479,7 +520,7 @@ public class ConnectionSupport { * it subsequently will throw an error. The latter will open/close the connection (internally) * and this can be repeated indefinitely. */ - public abstract static class BaseRConnection extends RConnection { + public abstract static class BaseRConnection implements RConnection { /** * {@code true} is the connection has been opened successfully. N.B. This supports lazy @@ -513,21 +554,84 @@ public class ConnectionSupport { */ private int descriptor; + private boolean blocking = true; + + /** + * The encoding to use to read or to write to the connection. + */ + private Charset encoding; + private ConnectionClass conClass; + private LinkedList<String> pushBack; + + /** + * Indicates that the last line read operation was incomplete.<br> + * This is only relevant for connections in text and non-blocking mode. + */ + private boolean incomplete = false; + /** * The constructor for every connection class except {@link StdConnections}. * * @param conClass the specific class of the connection, e.g, {@link ConnectionClass#File} * @param modeString the mode in which the connection should be opened, "" for lazy opening * @param defaultModeForLazy the mode to use when this connection is opened implicitly + * @param blocking Indicates if this connection has been openend in blocking mode. + * @param encoding The name of the encoding used to read from or to write to the connection + * ({@code null} is allowed and sets the character set to + * {@code Charset#defaultCharset()}). * */ - protected BaseRConnection(ConnectionClass conClass, String modeString, AbstractOpenMode defaultModeForLazy) throws IOException { + protected BaseRConnection(ConnectionClass conClass, String modeString, AbstractOpenMode defaultModeForLazy, boolean blocking, String encoding) throws IOException, IllegalCharsetNameException { this(conClass, new OpenMode(modeString, defaultModeForLazy)); if (conClass != ConnectionClass.Internal) { this.descriptor = getContextStateImpl().setConnection(this); } + this.blocking = blocking; + if (encoding != null) { + this.encoding = Charset.forName(ConnectionSupport.convertEncodingName(encoding)); + } else { + this.encoding = Charset.defaultCharset(); + } + } + + /** + * The constructor for every connection class except {@link StdConnections}. + * + * @param conClass the specific class of the connection, e.g, {@link ConnectionClass#File} + * @param modeString the mode in which the connection should be opened, "" for lazy opening + * @param defaultModeForLazy the mode to use when this connection is opened implicitly + * @param blocking Indicates if this connection has been openend in blocking mode. + * + */ + protected BaseRConnection(ConnectionClass conClass, String modeString, AbstractOpenMode defaultModeForLazy, boolean blocking) throws IOException { + this(conClass, modeString, defaultModeForLazy, blocking, null); + } + + /** + * The constructor for every connection class except {@link StdConnections}. + * + * @param conClass the specific class of the connection, e.g, {@link ConnectionClass#File} + * @param modeString the mode in which the connection should be opened, "" for lazy opening + * @param defaultModeForLazy the mode to use when this connection is opened implicitly + * @param encoding The name of the encoding used to read from or to write to the connection. + * + */ + protected BaseRConnection(ConnectionClass conClass, String modeString, AbstractOpenMode defaultModeForLazy, String encoding) throws IOException { + this(conClass, modeString, defaultModeForLazy, true, encoding); + } + + /** + * The constructor for every connection class except {@link StdConnections}. + * + * @param conClass the specific class of the connection, e.g, {@link ConnectionClass#File} + * @param modeString the mode in which the connection should be opened, "" for lazy opening + * @param defaultModeForLazy the mode to use when this connection is opened implicitly + * + */ + protected BaseRConnection(ConnectionClass conClass, String modeString, AbstractOpenMode defaultModeForLazy) throws IOException { + this(conClass, modeString, defaultModeForLazy, true, null); } /** @@ -546,8 +650,8 @@ public class ConnectionSupport { this.openMode = mode; } - public final ConnectionClass getConnectionClass() { - return conClass; + public String getConnectionClass() { + return conClass.getPrintName(); } /** @@ -605,8 +709,19 @@ public class ConnectionSupport { return getOpenMode().isText(); } + public boolean isBlocking() { + return blocking; + } + + /** + * Returns the original encoding string. + */ + public Charset getEncoding() { + return encoding; + } + @Override - public RConnection forceOpen(String modeString) throws IOException { + public BaseRConnection forceOpen(String modeString) throws IOException { if (closed) { throw new IOException(RError.Message.INVALID_CONNECTION.message); } @@ -626,11 +741,10 @@ public class ConnectionSupport { * This is used exclusively by the {@code open} builtin. */ public void open(String modeString) throws IOException { - if (openMode.abstractOpenMode == AbstractOpenMode.Lazy) { - // modeString may override the default - openMode = new OpenMode(modeString == null ? openMode.modeString : modeString); + openMode = new OpenMode(modeString == null ? openMode.modeString : modeString); + if (!isOpen()) { + createDelegateConnection(); } - createDelegateConnection(); } protected void checkOpen() { @@ -642,10 +756,9 @@ public class ConnectionSupport { opened = true; } - @Override - public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException { + protected String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException { checkOpen(); - return theConnection.readLinesInternal(n, warn, skipNul); + return theConnection.readLines(n, warn, skipNul); } @Override @@ -660,6 +773,12 @@ public class ConnectionSupport { return theConnection.getOutputStream(); } + @Override + public ByteChannel getChannel() throws IOException { + checkOpen(); + return theConnection; + } + @Override public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException { checkOpen(); @@ -736,8 +855,7 @@ public class ConnectionSupport { return theConnection.getc(); } - @Override - public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { + public long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { checkOpen(); return theConnection.seek(offset, seekMode, seekRWMode); } @@ -773,6 +891,13 @@ public class ConnectionSupport { return descriptor; } + /** + * Determines if the sources created by this connection are marked as internal. + */ + public boolean isInternal() { + return false; + } + public OpenMode getOpenMode() { return openMode; } @@ -780,345 +905,300 @@ public class ConnectionSupport { public boolean isClosed() { return closed; } - } - - public static BaseRConnection getBaseConnection(RConnection conn) { - if (conn instanceof BaseRConnection) { - return (BaseRConnection) conn; - } else if (conn instanceof DelegateReadRConnection) { - return ((DelegateReadRConnection) conn).base; - } else { - throw RInternalError.shouldNotReachHere(); - } - } - interface ReadWriteHelper { - - /** - * {@code readLines} from an {@link InputStream}. It would be convenient to use a - * {@link BufferedReader} but mixing binary and text operations, which is a requirement, - * would then be difficult. - * - * @param warn TODO - * @param skipNul TODO - */ - default String[] readLinesHelper(InputStream in, int n, boolean warn, boolean skipNul) throws IOException { - ArrayList<String> lines = new ArrayList<>(); - int totalRead = 0; - byte[] buffer = new byte[64]; - int pushBack = 0; - while (true) { - int ch; - if (pushBack != 0) { - ch = pushBack; - pushBack = 0; - } else { - ch = in.read(); - } - boolean lineEnd = false; - if (ch < 0) { - if (totalRead > 0) { - /* - * TODO GnuR says keep data and output a warning if blocking, otherwise - * silently push back. FastR doesn't support non-blocking yet, so we keep - * the data. Some refactoring is needed to be able to reliably access the - * "name" for the warning. - */ - lines.add(new String(buffer, 0, totalRead)); - if (warn) { - RError.warning(RError.SHOW_CALLER2, RError.Message.INCOMPLETE_FINAL_LINE, "TODO: connection path"); - } - } - break; - } - if (ch == '\n') { - lineEnd = true; - } else if (ch == '\r') { - lineEnd = true; - ch = in.read(); - if (ch == '\n') { - // swallow the trailing lf - } else { - pushBack = ch; - } - } - if (lineEnd) { - lines.add(new String(buffer, 0, totalRead)); - if (n > 0 && lines.size() == n) { - break; + private String readOneLineWithPushBack(List<String> res, int ind) { + String s = pushBack.pollLast(); + if (s == null) { + return null; + } else { + String[] lines = s.split("\n", 2); + if (lines.length == 2) { + // we hit end of the line + if (lines[1].length() != 0) { + // suffix is not empty and needs to be processed later + pushBack.push(lines[1]); } - totalRead = 0; + assert res.size() == ind; + res.add(ind, lines[0]); + return null; } else { - buffer = checkBuffer(buffer, totalRead); - buffer[totalRead++] = (byte) (ch & 0xFF); - } - } - String[] result = new String[lines.size()]; - lines.toArray(result); - return result; - } - - default void writeLinesHelper(OutputStream out, RAbstractStringVector lines, String sep) throws IOException { - for (int i = 0; i < lines.getLength(); i++) { - out.write(lines.getDataAt(i).getBytes()); - out.write(sep.getBytes()); - } - } - - default void writeStringHelper(OutputStream out, String s, boolean nl) throws IOException { - out.write(s.getBytes()); - if (nl) { - out.write('\n'); - } - } + // no end of the line found yet + StringBuilder sb = new StringBuilder(); + do { + assert lines.length == 1; + sb.append(lines[0]); + s = pushBack.pollLast(); + if (s == null) { + break; + } - default void writeCharHelper(OutputStream out, String s, int pad, String eos) throws IOException { - out.write(s.getBytes()); - if (pad > 0) { - for (int i = 0; i < pad; i++) { - out.write(0); + lines = s.split("\n", 2); + if (lines.length == 2) { + // we hit end of the line + if (lines[1].length() != 0) { + // suffix is not empty and needs to be processed later + pushBack.push(lines[1]); + } + assert res.size() == ind; + res.add(ind, sb.append(lines[0]).toString()); + return null; + } // else continue + } while (true); + return sb.toString(); } } - if (eos != null && eos.length() > 0) { - out.write(eos.getBytes()); - } - } - - default void writeBinHelper(ByteBuffer buffer, OutputStream outputStream) throws IOException { - int n = buffer.remaining(); - byte[] b = new byte[n]; - buffer.get(b); - outputStream.write(b); } /** - * Reads null-terminated character strings from an {@link InputStream}. + * TODO(fa) This method is subject for refactoring. I modified the original implementation + * to be capable to handle a negative 'n' parameter. It indicates to read as much lines as + * available. */ - default byte[] readBinCharsHelper(InputStream in) throws IOException { - int ch = in.read(); - if (ch < 0) { - return null; - } - int totalRead = 0; - byte[] buffer = new byte[64]; - while (true) { - buffer = checkBuffer(buffer, totalRead); - buffer[totalRead++] = (byte) (ch & 0xFF); - if (ch == 0) { - break; - } - ch = in.read(); + @TruffleBoundary + private String[] readLinesWithPushBack(int n, boolean warn, boolean skipNul) throws IOException { + // NOTE: 'n' may be negative indicating to read as much lines as available + final List<String> res; + if (n >= 0) { + res = new ArrayList<>(n); + } else { + res = new ArrayList<>(); } - return buffer; - } - default int readBinHelper(ByteBuffer buffer, InputStream inputStream) throws IOException { - int bytesToRead = buffer.remaining(); - byte[] b = new byte[bytesToRead]; - int totalRead = 0; - int thisRead = 0; - while ((totalRead < bytesToRead) && ((thisRead = inputStream.read(b, totalRead, bytesToRead - totalRead)) > 0)) { - totalRead += thisRead; - } - buffer.put(b, 0, totalRead); - return totalRead; - } + for (int i = 0; i < n || n < 0; i++) { + String s = readOneLineWithPushBack(res, i); + final int remainingLineCount = n >= 0 ? n - i : n; + if (s == null) { + if (i >= res.size() || res.get(i) == null) { + // no more push back value - default String readCharHelper(int nchars, InputStream in, @SuppressWarnings("unused") boolean useBytes) throws IOException { - byte[] bytes = new byte[nchars]; - in.read(bytes); - int j = 0; - for (; j < bytes.length; j++) { - // strings end at 0 - if (bytes[j] == 0) { + String[] resInternal = readLinesInternal(remainingLineCount, warn, skipNul); + res.addAll(Arrays.asList(resInternal)); + pushBack = null; + break; + } + // else res[i] has been filled - move to trying to fill the next one + } else { + // reached the last push back value without reaching and of line + assert pushBack.size() == 0; + String[] resInternal = readLinesInternal(remainingLineCount, warn, skipNul); + res.addAll(i, Arrays.asList(resInternal)); + if (res.get(i) != null) { + res.set(i, s + res.get(i)); + } else { + res.set(i, s); + } + pushBack = null; break; } } - return new String(bytes, 0, j); - } - } - - private static byte[] checkBuffer(byte[] buffer, int n) { - if (n > buffer.length - 1) { - byte[] newBuffer = new byte[buffer.length + buffer.length / 2]; - System.arraycopy(buffer, 0, newBuffer, 0, buffer.length); - return newBuffer; - } else { - return buffer; - } - } - - abstract static class DelegateRConnection extends RConnection { - protected BaseRConnection base; - - DelegateRConnection(BaseRConnection base) { - this.base = base; - } - - @Override - public int getDescriptor() { - return base.getDescriptor(); + return res.toArray(new String[res.size()]); } @Override - public boolean isTextMode() { - return base.isTextMode(); + public String[] readLines(int n, boolean warn, boolean skipNul) throws IOException { + if (pushBack == null) { + return readLinesInternal(n, warn, skipNul); + } else if (pushBack.size() == 0) { + pushBack = null; + return readLinesInternal(n, warn, skipNul); + } else { + return readLinesWithPushBack(n, warn, skipNul); + } } + /** + * Pushes lines back to the connection. + */ @Override - public boolean isOpen() { - return base.isOpen(); + @TruffleBoundary + public final void pushBack(RAbstractStringVector lines, boolean addNewLine) { + if (pushBack == null) { + pushBack = new LinkedList<>(); + } + for (int i = 0; i < lines.getLength(); i++) { + String newLine = lines.getDataAt(i); + if (addNewLine) { + newLine = newLine + '\n'; + } + pushBack.addFirst(newLine); + } } - @Override - public RConnection forceOpen(String modeString) throws IOException { - return base.forceOpen(modeString); + /** + * Return the length of the push back. + */ + @TruffleBoundary + public final int pushBackLength() { + return pushBack == null ? 0 : pushBack.size(); } - @Override - public boolean isSeekable() { - return false; + /** + * Clears the pushback. + */ + @TruffleBoundary + public final void pushBackClear() { + pushBack = null; } + /** + * Support for {@code seek} Internal. Also clears push back lines. + */ @Override public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { - throw RError.error(RError.SHOW_CALLER2, RError.Message.UNSEEKABLE_CONNECTION); - } - } - - abstract static class DelegateReadRConnection extends DelegateRConnection { - protected DelegateReadRConnection(BaseRConnection base) { - super(base); + if (isSeekable()) { + // discard any push back strings + pushBackClear(); + } + // Do not throw error at this position, since the error messages varies depending on the + // connection. + return seekInternal(offset, seekMode, seekRWMode); } @Override - public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException { - throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message); + public void truncate() throws IOException { + checkOpen(); + if (!closed && opened) { + theConnection.truncate(); + } else { + throw RError.error(RError.SHOW_CALLER, RError.Message.TRUNCATE_ONLY_OPEN_CONN); + } } - @Override - public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException { - throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message); + /** + * Returns {@code true} iff the last read operation was blocked or there is unflushed + * output. + */ + public boolean isIncomplete() { + return incomplete; } - @Override - public void writeString(String s, boolean nl) throws IOException { - throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message); + protected void setIncomplete(boolean b) { + this.incomplete = b; } - @Override - public void writeBin(ByteBuffer buffer) throws IOException { - throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message); - } + public final RAbstractIntVector asVector() { + String[] classes = new String[]{ConnectionSupport.getBaseConnection(this).getConnectionClass(), "connection"}; - @Override - public int getc() throws IOException { - return getInputStream().read(); - } + RAbstractIntVector result = RDataFactory.createIntVector(new int[]{getDescriptor()}, true); - @Override - public void flush() { - // nothing to do + RStringVector classVector = RDataFactory.createStringVector(classes, RDataFactory.COMPLETE_VECTOR); + // it's important to put "this" into the externalptr, so that it doesn't get collected + RExternalPtr connectionId = RDataFactory.createExternalPtr(null, this, RDataFactory.createSymbol("connection"), RNull.instance); + DynamicObject attrs = RAttributesLayout.createClassWithConnId(classVector, connectionId); + result.initAttributes(attrs); + return result; } + } - @Override - public OutputStream getOutputStream() { + public static BaseRConnection getBaseConnection(RConnection conn) { + if (conn instanceof BaseRConnection) { + return (BaseRConnection) conn; + } else if (conn instanceof DelegateReadRConnection) { + return ((DelegateRConnection) conn).base; + } else { throw RInternalError.shouldNotReachHere(); } - - @Override - public boolean canRead() { - return true; - } - - @Override - public boolean canWrite() { - return false; - } } - abstract static class DelegateWriteRConnection extends DelegateRConnection { - protected DelegateWriteRConnection(BaseRConnection base) { - super(base); - } + abstract static class BasePathRConnection extends BaseRConnection { + /** The path of the actual file to open. */ + protected final String path; - @Override - public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException { - throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message); - } + /** The description used in the call (required summary output). */ + protected final String description; - @Override - public String readChar(int nchars, boolean useBytes) throws IOException { - throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message); + protected BasePathRConnection(String description, String path, ConnectionClass connectionClass, String modeString, String encoding) throws IOException { + this(description, path, connectionClass, modeString, AbstractOpenMode.Read, encoding); } - @Override - public int readBin(ByteBuffer buffer) throws IOException { - throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message); + protected BasePathRConnection(String description, String path, ConnectionClass connectionClass, String modeString, boolean blocking, String encoding) throws IOException { + this(description, path, connectionClass, modeString, AbstractOpenMode.Read, blocking, encoding); } - @Override - public byte[] readBinChars() throws IOException { - throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message); + protected BasePathRConnection(String description, String path, ConnectionClass connectionClass, String modeString, AbstractOpenMode defaultLazyOpenMode, String encoding) throws IOException { + super(connectionClass, modeString, defaultLazyOpenMode, encoding); + this.path = Utils.tildeExpand(path); + this.description = description; } - @Override - public int getc() throws IOException { - throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message); + protected BasePathRConnection(String description, String path, ConnectionClass connectionClass, String modeString, AbstractOpenMode defaultLazyOpenMode, boolean blocking, String encoding) + throws IOException { + super(connectionClass, modeString, defaultLazyOpenMode, blocking, encoding); + this.path = Utils.tildeExpand(path); + this.description = description; } @Override - public InputStream getInputStream() { - throw RInternalError.shouldNotReachHere(); + public String getSummaryDescription() { + // Use 'description' and not 'path' since this may be different, e.g., on temp files. + return description; } + } - @Override - public boolean canRead() { - return false; - } + public static ByteChannel newChannel(InputStream in) { + final ReadableByteChannel newChannel = Channels.newChannel(in); + return new ByteChannel() { - @Override - public boolean canWrite() { - return true; - } - } + @Override + public int read(ByteBuffer dst) throws IOException { + return newChannel.read(dst); + } - abstract static class DelegateReadWriteRConnection extends DelegateRConnection { - protected DelegateReadWriteRConnection(BaseRConnection base) { - super(base); - } + @Override + public boolean isOpen() { + return newChannel.isOpen(); + } - @Override - public boolean canRead() { - return true; - } + @Override + public void close() throws IOException { + newChannel.close(); - @Override - public boolean canWrite() { - return true; - } + } - @Override - public int getc() throws IOException { - return getInputStream().read(); - } + @Override + public int write(ByteBuffer src) throws IOException { + throw new IOException("This channel is read-only."); + } + }; } - abstract static class BasePathRConnection extends BaseRConnection { - protected final String path; + public static ByteChannel newChannel(OutputStream out) { + final WritableByteChannel newChannel = Channels.newChannel(out); + return new ByteChannel() { - protected BasePathRConnection(String path, ConnectionClass connectionClass, String modeString) throws IOException { - this(path, connectionClass, modeString, AbstractOpenMode.Read); - } + @Override + public int read(ByteBuffer dst) throws IOException { + throw new IOException("This channel is write-only."); + } - protected BasePathRConnection(String path, ConnectionClass connectionClass, String modeString, AbstractOpenMode defaultLazyOpenMode) throws IOException { - super(connectionClass, modeString, defaultLazyOpenMode); - this.path = Utils.tildeExpand(path); - } + @Override + public boolean isOpen() { + return newChannel.isOpen(); + } - @Override - public String getSummaryDescription() { - return path; + @Override + public void close() throws IOException { + newChannel.close(); + + } + + @Override + public int write(ByteBuffer src) throws IOException { + return newChannel.write(src); + } + }; + } + + /** + * Converts between character set names of iconv and Java. + * + * @param encoding The iconv name of the character set to use. + * @return The Java name of the character set to use. + */ + public static String convertEncodingName(String encoding) { + if (encoding == null || encoding.isEmpty() || "native.enc".equals(encoding)) { + return Charset.defaultCharset().name(); } + return encoding; } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java new file mode 100644 index 0000000000000000000000000000000000000000..d43eeb8e783e736fc98265c4972b04c6e6cd8f68 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java @@ -0,0 +1,593 @@ +/* + * 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 + * 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.runtime.conn; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.nio.ByteBuffer; +import java.nio.channels.ByteChannel; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.SeekableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CodingErrorAction; +import java.util.ArrayList; +import java.util.Objects; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; + +/** + * Actually performs the I/O operations for a connections.<br> + * <p> + * A delegate connection is called from its base connection and implements the actual I/O + * operations. + * </p> + */ +abstract class DelegateRConnection implements RConnection, ByteChannel { + private static final int DEFAULT_CACHE_SIZE = 16 * 1024; + protected final BaseRConnection base; + private final ByteBuffer cache; + + DelegateRConnection(BaseRConnection base) { + this(base, DEFAULT_CACHE_SIZE); + } + + DelegateRConnection(BaseRConnection base, int cacheSize) { + this.base = Objects.requireNonNull(base); + + if (cacheSize > 0) { + cache = ByteBuffer.allocate(cacheSize); + // indicate that there are no remaining bytes in the buffer + cache.flip(); + } else { + cache = null; + } + } + + @Override + public int getDescriptor() { + return base.getDescriptor(); + } + + @Override + public boolean isTextMode() { + return base.isTextMode(); + } + + @Override + public boolean isOpen() { + return base.isOpen(); + } + + @Override + public RConnection forceOpen(String modeString) throws IOException { + return base.forceOpen(modeString); + } + + @SuppressWarnings("unused") + protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { + throw RInternalError.shouldNotReachHere("seek has not been implemented for this connection"); + } + + @Override + public final long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { + if (!isSeekable()) { + throw RError.error(RError.SHOW_CALLER, RError.Message.NOT_ENABLED_FOR_THIS_CONN, "seek"); + } + final long res = seekInternal(offset, seekMode, seekRWMode); + invalidateCache(); + return res; + } + + /** + * {@code readLines} from the connection. It would be convenient to use a {@link BufferedReader} + * but mixing binary and text operations, which is a requirement, would then be difficult. + * + * @param warn Specifies if warnings should be output. + * @param skipNul Specifies if the null character should be ignored. + */ + @Override + @TruffleBoundary + public String[] readLines(int n, boolean warn, boolean skipNul) throws IOException { + base.setIncomplete(false); + ArrayList<String> lines = new ArrayList<>(); + int totalRead = 0; + int nBytesConsumed = 0; + byte[] buffer = new byte[64]; + int pushBack = 0; + boolean nullRead = false; + while (true) { + int ch; + if (pushBack != 0) { + ch = pushBack; + pushBack = 0; + } else { + ch = readInternal(); + } + boolean lineEnd = false; + if (ch < 0) { + if (totalRead > 0) { + /* + * GnuR says if non-blocking and in text mode, silently push back incomplete + * lines, otherwise keep data and output warning. + */ + final String incompleteFinalLine = new String(buffer, 0, totalRead, base.getEncoding()); + nBytesConsumed += totalRead; + if (!base.isBlocking() && base.isTextMode()) { + base.pushBack(RDataFactory.createStringVector(incompleteFinalLine), false); + base.setIncomplete(true); + } else { + lines.add(incompleteFinalLine); + if (warn) { + RError.warning(RError.SHOW_CALLER, RError.Message.INCOMPLETE_FINAL_LINE, base.getSummaryDescription()); + } + } + } + break; + } + if (ch == '\n') { + lineEnd = true; + } else if (ch == '\r') { + lineEnd = true; + ch = readInternal(); + if (ch == '\n') { + // swallow the trailing lf + } else { + pushBack = ch; + } + } else if (ch == 0) { + nullRead = true; + if (warn && !skipNul) { + RError.warning(RError.SHOW_CALLER, RError.Message.LINE_CONTAINS_EMBEDDED_NULLS, lines.size() + 1); + } + } + if (lineEnd) { + lines.add(new String(buffer, 0, totalRead, base.getEncoding())); + nBytesConsumed += totalRead; + if (n > 0 && lines.size() == n) { + break; + } + totalRead = 0; + nullRead = false; + } else { + if (!nullRead) { + buffer = DelegateRConnection.checkBuffer(buffer, totalRead); + buffer[totalRead++] = (byte) (ch & 0xFF); + } + if (skipNul) { + nullRead = false; + } + } + } + String[] result = new String[lines.size()]; + lines.toArray(result); + updateReadOffset(nBytesConsumed); + return result; + } + + /** + * Updates the read cursor.<br> + * <p> + * Called by methods using {@link #readInternal()} to tell how many bytes have been consumed to + * be able to update a read curosor if available. + * </p> + * + * @param nBytesConsumed Number of bytes consumed by a read operation. + */ + protected void updateReadOffset(int nBytesConsumed) { + // default: nothing to do + } + + @Override + public String readChar(int nchars, boolean useBytes) throws IOException { + if (useBytes) { + return DelegateRConnection.readCharHelper(nchars, this); + } else { + return DelegateRConnection.readCharHelper(nchars, getDecoder(nchars)); + } + } + + /** + * Writes a string to a channel. + * + * @param out the channel + * @param s The actual string to write. + * @param nl Indicates if a line separator should be appended. + * @param encoding The encoding to use for writing. + * @return {@code true} if an incomplete line was written; {@code false} otherwise + * @throws IOException + */ + @TruffleBoundary + public static boolean writeStringHelper(WritableByteChannel out, String s, boolean nl, Charset encoding) throws IOException { + boolean incomplete; + final byte[] bytes = s.getBytes(encoding); + final byte[] lineSepBytes = nl ? System.lineSeparator().getBytes(encoding) : null; + + ByteBuffer buf = ByteBuffer.allocate(bytes.length + (nl ? lineSepBytes.length : 0)); + buf.put(bytes); + if (nl) { + buf.put(lineSepBytes); + incomplete = false; + } else { + incomplete = !s.contains("\n"); + } + + buf.rewind(); + out.write(buf); + return incomplete; + } + + /** + * Writes characters in binary mode (without any re-encoding) to the provided channel. + * + * @param channel The writable byte channel to write to (must not be {@code null}). + * @param s The character string to write (must not be {@code null}). + * @param pad The number of null characters to append to the characters. + * @param eos The end-of-string terminator (may be {@code null}). + * @throws IOException + */ + @TruffleBoundary + public static void writeCharHelper(WritableByteChannel channel, String s, int pad, String eos) throws IOException { + + final byte[] bytes = s.getBytes(); + final byte[] eosBytes = eos != null ? eos.getBytes() : null; + + final int bufLen = bytes.length + (pad > 0 ? pad : 0) + (eos != null ? eosBytes.length + 1 : 0); + assert bufLen >= s.length(); + ByteBuffer buf = ByteBuffer.allocate(bufLen); + buf.put(bytes); + if (pad > 0) { + for (int i = 0; i < pad; i++) { + buf.put((byte) 0); + } + } + if (eos != null) { + if (eos.length() > 0) { + buf.put(eos.getBytes()); + } + // function writeChar is defined to append the null character if eos != null + buf.put((byte) 0); + } + buf.rewind(); + channel.write(buf); + } + + /** + * Reads a specified amount of characters. + * + * @param nchars Number of characters to read. + * @param in The encoded byte stream. + * @return The read string. + * @throws IOException + */ + public static String readCharHelper(int nchars, Reader in) throws IOException { + char[] chars = new char[nchars]; + in.read(chars); + int j = 0; + for (; j < chars.length; j++) { + // strings end at 0 + if (chars[j] == 0) { + break; + } + } + + return new String(chars, 0, j); + } + + /** + * Reads a specified number of single-byte characters.<br> + * <p> + * This method is meant to be used if R's function {@code readChar} is called with parameter + * {@code useBytes=TRUE}. + * </p> + * + * @param nchars The number of single-byte characters to read. + * @param channel The channel to read from (must not be {@code null}). + * @throws IOException + */ + public static String readCharHelper(int nchars, ReadableByteChannel channel) throws IOException { + ByteBuffer buf = ByteBuffer.allocate(nchars); + channel.read(buf); + int j = 0; + for (; j < buf.position(); j++) { + // strings end at 0 + if (buf.get(j) == 0) { + break; + } + } + + return new String(buf.array(), 0, j); + } + + /** + * Implements standard seeking behavior.<br> + * <p> + * <it>Standard</it> means that there is a shared cursor between reading and writing operations. + * </p> + */ + public static long seek(SeekableByteChannel channel, long offset, SeekMode seekMode, @SuppressWarnings("unused") SeekRWMode seekRWMode) throws IOException { + long position = channel.position(); + switch (seekMode) { + case ENQUIRE: + break; + case CURRENT: + if (offset != 0) { + channel.position(position + offset); + } + break; + case START: + channel.position(offset); + break; + case END: + throw RInternalError.unimplemented(); + + } + return position; + } + + /** + * Enlarges the buffer if necessary. + */ + private static byte[] checkBuffer(byte[] buffer, int n) { + if (n > buffer.length - 1) { + byte[] newBuffer = new byte[buffer.length + buffer.length / 2]; + System.arraycopy(buffer, 0, newBuffer, 0, buffer.length); + return newBuffer; + } else { + return buffer; + } + } + + @TruffleBoundary + public static boolean writeLinesHelper(WritableByteChannel out, RAbstractStringVector lines, String sep, Charset encoding) throws IOException { + if (sep != null && sep.contains("\n")) { + // fast path: we know that the line is complete + final ByteBuffer nlBuf = ByteBuffer.wrap(sep.getBytes(encoding)); + for (int i = 0; i < lines.getLength(); i++) { + final String line = lines.getDataAt(i); + final ByteBuffer buf = ByteBuffer.wrap(line.getBytes(encoding)); + out.write(buf); + nlBuf.rewind(); + out.write(nlBuf); + } + return false; + } else { + // slow path: we have to scan every string if it contains a newline + boolean incomplete = false; + for (int i = 0; i < lines.getLength(); i++) { + final String line = lines.getDataAt(i); + incomplete = DelegateRConnection.writeStringHelper(out, line, false, encoding); + incomplete = DelegateRConnection.writeStringHelper(out, sep, false, encoding) || incomplete; + } + return incomplete; + } + } + + @Override + public void pushBack(RAbstractStringVector lines, boolean addNewLine) { + throw RInternalError.shouldNotReachHere(); + } + + /** + * Creates the stream decoder on demand and returns it. + */ + protected Reader getDecoder(int bufSize) { + CharsetDecoder charsetEncoder = base.getEncoding().newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE); + return Channels.newReader(this, charsetEncoder, bufSize); + } + + @Override + public void truncate() throws IOException { + if (!isSeekable()) { + throw RError.error(RError.SHOW_CALLER, RError.Message.TRUNCATE_NOT_ENABLED); + } + throw RError.nyi(RError.SHOW_CALLER, "truncate"); + } + + @Override + public void writeBin(ByteBuffer buffer) throws IOException { + write(buffer); + } + + @Override + public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException { + DelegateRConnection.writeCharHelper(this, s, pad, eos); + } + + @Override + public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException { + boolean incomplete = DelegateRConnection.writeLinesHelper(this, lines, sep, base.getEncoding()); + base.setIncomplete(incomplete); + } + + @Override + public void writeString(String s, boolean nl) throws IOException { + DelegateRConnection.writeStringHelper(this, s, nl, base.getEncoding()); + } + + @Override + @TruffleBoundary + public int read(ByteBuffer dst) throws IOException { + if (cache != null) { + final int bytesRequested = dst.remaining(); + int totalBytesRead = 0; + int bytesToRead = 0; + boolean eof; + do { + eof = ensureDataAvailable(dst.remaining()); + bytesToRead = Math.min(cache.remaining(), dst.remaining()); + cache.get(dst.array(), dst.position(), bytesToRead); + dst.position(dst.position() + bytesToRead); + totalBytesRead += bytesToRead; + } while (totalBytesRead < bytesRequested && bytesToRead > 0 && !eof); + return totalBytesRead == 0 && eof ? -1 : totalBytesRead; + } else { + return getChannel().read(dst); + } + } + + @Override + @TruffleBoundary + public int write(ByteBuffer src) throws IOException { + return getChannel().write(src); + } + + /** + * Reads one byte from the channel.<br> + * <p> + * Should basically do the same job as {@link #getc()} but is only used by internally by this + * class or subclasses an may therefore produce an inconsistent state over several calls. For + * example, updating the channel's cursor position can be collapsed. + * </p> + */ + protected int readInternal() throws IOException { + if (cache != null) { + ensureDataAvailable(1); + if (!cache.hasRemaining()) { + return -1; + } + // consider byte to be unsigned + return cache.get() & 0xFF; + } else { + + ByteBuffer buf = ByteBuffer.allocate(1); + int n = getChannel().read(buf); + if (n <= 0) { + return -1; + } + buf.flip(); + return buf.get() & 0xFF; + } + } + + private boolean ensureDataAvailable(int i) throws IOException { + assert cache != null; + if (cache.remaining() < i) { + byte[] rem = new byte[cache.remaining()]; + cache.get(rem); + assert !cache.hasRemaining(); + cache.clear(); + cache.put(rem); + int read = getChannel().read(cache); + cache.flip(); + return read == -1; + } + return false; + } + + /** + * Invalidates the read cache by dropping cached data.<br> + * <p> + * This method is most useful if an operation like {@code seek} is performed that destroys the + * order data is read. + * </p> + */ + protected void invalidateCache() { + if (cache != null) { + cache.clear(); + cache.flip(); + } + } + + @Override + public int getc() throws IOException { + return readInternal(); + } + + @Override + public int readBin(ByteBuffer buffer) throws IOException { + int read = read(buffer); + return read < 0 ? 0 : read; + } + + /** + * Reads null-terminated character strings from a {@link ReadableByteChannel}. + */ + @Override + public byte[] readBinChars() throws IOException { + int numRead = readInternal(); + if (numRead <= 0) { + return null; + } + int totalRead = 0; + byte[] buffer = new byte[64]; + while (true) { + buffer = DelegateRConnection.checkBuffer(buffer, totalRead); + buffer[totalRead++] = (byte) numRead; + if (numRead == 0) { + break; + } else if (numRead == -1) { + RError.warning(RError.SHOW_CALLER, RError.Message.INCOMPLETE_STRING_AT_EOF_DISCARDED); + return null; + } + numRead = readInternal(); + } + return buffer; + } + + @Override + public boolean canRead() { + return true; + } + + @Override + public boolean canWrite() { + return true; + } + + @Override + public void flush() throws IOException { + // nothing to do for channels + } + + @Override + public OutputStream getOutputStream() throws IOException { + return Channels.newOutputStream(this); + } + + @Override + public InputStream getInputStream() throws IOException { + return Channels.newInputStream(this); + } + + @Override + public void close() throws IOException { + getChannel().close(); + } + + @Override + public void closeAndDestroy() throws IOException { + base.closed = true; + close(); + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java new file mode 100644 index 0000000000000000000000000000000000000000..d4b11c2d5723c037e1839c5f26b05f31b6e98bb5 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java @@ -0,0 +1,84 @@ +/* + * 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 + * 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.runtime.conn; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.ByteBuffer; + +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; + +public abstract class DelegateReadRConnection extends DelegateRConnection { + + protected DelegateReadRConnection(BaseRConnection base) { + super(base); + } + + protected DelegateReadRConnection(BaseRConnection base, int cacheSize) { + super(base, cacheSize); + } + + @Override + public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException { + throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message); + } + + @Override + public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException { + throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message); + } + + @Override + public void writeString(String s, boolean nl) throws IOException { + throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message); + } + + @Override + public void writeBin(ByteBuffer buffer) throws IOException { + throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message); + } + + @Override + public OutputStream getOutputStream() { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public boolean canRead() { + return true; + } + + @Override + public boolean canWrite() { + return false; + } + + @Override + public void truncate() { + throw RError.error(RError.SHOW_CALLER, RError.Message.TRUNCATE_ONLY_WRITE_CONNECTION); + } + +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java new file mode 100644 index 0000000000000000000000000000000000000000..c445251b02495f80207f0c2507bcc046e64eadb9 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java @@ -0,0 +1,37 @@ +/* + * 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 + * 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.runtime.conn; + +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection; + +abstract class DelegateReadWriteRConnection extends DelegateRConnection { + + protected DelegateReadWriteRConnection(BaseRConnection base) { + super(base); + } + + protected DelegateReadWriteRConnection(BaseRConnection base, int cacheSize) { + super(base, cacheSize); + } + +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java new file mode 100644 index 0000000000000000000000000000000000000000..16503501a0914f0e299d5e7c06f1eda99d0d4e88 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java @@ -0,0 +1,78 @@ +/* + * 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 + * 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.runtime.conn; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; + +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection; + +abstract class DelegateWriteRConnection extends DelegateRConnection { + + protected DelegateWriteRConnection(BaseRConnection base) { + super(base, 0); + } + + @Override + public String[] readLines(int n, boolean warn, boolean skipNul) throws IOException { + throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message); + } + + @Override + public String readChar(int nchars, boolean useBytes) throws IOException { + throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message); + } + + @Override + public int readBin(ByteBuffer buffer) throws IOException { + throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message); + } + + @Override + public byte[] readBinChars() throws IOException { + throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message); + } + + @Override + public int getc() throws IOException { + throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message); + } + + @Override + public InputStream getInputStream() { + throw RInternalError.shouldNotReachHere(); + } + + @Override + public boolean canRead() { + return false; + } + + @Override + public boolean canWrite() { + return true; + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java new file mode 100644 index 0000000000000000000000000000000000000000..ed9b67884e082b0043be6c6457567737bc1aeb92 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java @@ -0,0 +1,299 @@ +/* + * 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 + * 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.runtime.conn; + +import java.io.IOException; +import java.io.InputStream; +import java.io.RandomAccessFile; +import java.lang.ProcessBuilder.Redirect; +import java.nio.channels.ByteChannel; +import java.nio.channels.FileChannel; +import java.nio.channels.SeekableByteChannel; +import java.nio.file.Files; +import java.nio.file.OpenOption; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.Arrays; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.r.runtime.ProcessOutputManager; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass; + +public class FifoConnections { + + public static class FifoRConnection extends BaseRConnection { + + private final String path; + + public FifoRConnection(String path, String open, boolean blocking, String encoding) throws IOException { + super(ConnectionClass.FIFO, open, AbstractOpenMode.Read, blocking, encoding); + this.path = path; + openNonLazyConnection(); + } + + @Override + @TruffleBoundary + protected void createDelegateConnection() throws IOException { + final DelegateRConnection delegate; + if (isBlocking()) { + delegate = createBlockingDelegate(); + } else { + + delegate = createNonBlockingDelegate(); + } + setDelegate(delegate); + } + + private DelegateRConnection createBlockingDelegate() throws IOException { + DelegateRConnection delegate = null; + switch (getOpenMode().abstractOpenMode) { + case Read: + case ReadBinary: + delegate = new FifoReadRConnection(this, path); + break; + case Write: + case WriteBinary: + delegate = new FifoWriteConnection(this, path); + break; + case ReadAppend: + case ReadWrite: + case ReadWriteBinary: + case ReadWriteTrunc: + case ReadWriteTruncBinary: + delegate = new FifoReadWriteConnection(this, path); + break; + default: + throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + getOpenMode()); + } + return delegate; + } + + private DelegateRConnection createNonBlockingDelegate() throws IOException { + DelegateRConnection delegate = null; + switch (getOpenMode().abstractOpenMode) { + case Read: + case ReadBinary: + delegate = new FifoReadNonBlockingRConnection(this, path); + break; + case Write: + case WriteBinary: + delegate = new FifoWriteNonBlockingRConnection(this, path); + break; + case ReadAppend: + case ReadWrite: + case ReadWriteBinary: + case ReadWriteTrunc: + case ReadWriteTruncBinary: + delegate = new FifoReadWriteNonBlockingRConnection(this, path); + break; + default: + throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + getOpenMode()); + } + return delegate; + } + + @Override + public String getSummaryDescription() { + return path; + } + } + + static class FifoReadRConnection extends DelegateReadRConnection { + private final FileChannel channel; + + protected FifoReadRConnection(BaseRConnection base, String path) throws IOException { + super(base); + channel = FileChannel.open(Paths.get(path), StandardOpenOption.READ); + } + + @Override + public ByteChannel getChannel() { + return channel; + } + + @Override + public boolean isSeekable() { + return false; + } + } + + private static class FifoWriteConnection extends DelegateWriteRConnection { + private final RandomAccessFile raf; + + FifoWriteConnection(BaseRConnection base, String path) throws IOException { + super(base); + this.raf = createAndOpenFifo(path, "rw"); + } + + @Override + public SeekableByteChannel getChannel() { + return raf.getChannel(); + } + + @Override + public void close() throws IOException { + raf.close(); + } + + @Override + public boolean isSeekable() { + return false; + } + } + + private static class FifoReadWriteConnection extends DelegateReadWriteRConnection { + + private final RandomAccessFile raf; + + protected FifoReadWriteConnection(BaseRConnection base, String path) throws IOException { + super(base); + this.raf = createAndOpenFifo(path, "rw"); + } + + @Override + public boolean isSeekable() { + return false; + } + + @Override + public ByteChannel getChannel() { + return raf.getChannel(); + } + + } + + static class FifoReadNonBlockingRConnection extends DelegateReadRConnection { + private final FileChannel channel; + + protected FifoReadNonBlockingRConnection(BaseRConnection base, String path) throws IOException { + super(base); + channel = FileChannel.open(Paths.get(path), StandardOpenOption.READ); + } + + @Override + public SeekableByteChannel getChannel() { + return channel; + } + + @Override + public boolean isSeekable() { + return false; + } + } + + private static class FifoWriteNonBlockingRConnection extends DelegateWriteRConnection { + private final FileChannel channel; + + FifoWriteNonBlockingRConnection(BaseRConnection base, String path) throws IOException { + super(base); + channel = createAndOpenNonBlockingFifo(path, StandardOpenOption.READ, StandardOpenOption.WRITE); + } + + @Override + public SeekableByteChannel getChannel() { + return channel; + } + + @Override + public boolean isSeekable() { + return false; + } + } + + private static class FifoReadWriteNonBlockingRConnection extends DelegateReadWriteRConnection { + private final FileChannel channel; + + FifoReadWriteNonBlockingRConnection(BaseRConnection base, String path) throws IOException { + super(base); + channel = createAndOpenNonBlockingFifo(path, StandardOpenOption.WRITE, StandardOpenOption.READ); + } + + @Override + public SeekableByteChannel getChannel() { + return channel; + } + + @Override + public boolean isSeekable() { + return false; + } + + } + + private static final String MKFIFO_ERROR_FILE_EXISTS = "File exists"; + + private static RandomAccessFile createAndOpenFifo(String path, String mode) throws IOException { + if (!Files.exists(Paths.get(path))) { + // try to create fifo on demand + createNamedPipe(path); + } + return new RandomAccessFile(path, mode); + } + + private static FileChannel createAndOpenNonBlockingFifo(String path, OpenOption... openOptions) throws IOException { + if (!Files.exists(Paths.get(path))) { + // try to create fifo on demand + createNamedPipe(path); + } + return FileChannel.open(Paths.get(path), openOptions); + } + + /** + * Creates a named pipe (FIFO) by invoking {@code mkfifo} in a shell. + * + * <b>NOTE:</b> This is a Linux-specific operation and won't work on other OSes. + * + * @param path The path to the named pipe. + * @throws IOException + */ + @TruffleBoundary + private static void createNamedPipe(String path) throws IOException { + + String[] command = new String[]{"mkfifo", path}; + ProcessBuilder pb = new ProcessBuilder(command); + pb.redirectError(Redirect.INHERIT); + Process p = pb.start(); + InputStream is = p.getInputStream(); + ProcessOutputManager.OutputThreadVariable readThread = new ProcessOutputManager.OutputThreadVariable(command[0], is); + readThread.start(); + try { + int rc = p.waitFor(); + if (rc == 0) { + readThread.join(); + String msg = new String(Arrays.copyOf(readThread.getData(), readThread.getTotalRead())); + + // if the message is not empty and it is not the "file exists" error, then throw + // error + if (!msg.isEmpty() && !msg.endsWith(MKFIFO_ERROR_FILE_EXISTS)) { + throw new IOException(msg); + } + } + } catch (InterruptedException ex) { + // fall through + } + } + +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java index 77c0e2875edf4e45f279d1eea5742f279efdd91d..b14529c998dfd7df4fa202a0df4e432724a99b7c 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java @@ -22,9 +22,8 @@ */ package com.oracle.truffle.r.runtime.conn; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; @@ -32,34 +31,46 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; import java.nio.ByteBuffer; +import java.nio.channels.ByteChannel; +import java.nio.channels.FileChannel; +import java.nio.file.OpenOption; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.List; import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; +import org.tukaani.xz.LZMA2Options; +import org.tukaani.xz.XZ; import org.tukaani.xz.XZInputStream; +import org.tukaani.xz.XZOutputStream; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RCompression; +import com.oracle.truffle.r.runtime.RCompression.Type; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.TempPathName; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode; import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BasePathRConnection; import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadRConnection; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadWriteRConnection; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateWriteRConnection; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.OpenMode; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ReadWriteHelper; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; public class FileConnections { + public static final int GZIP_BUFFER_SIZE = (2 << 20); + /** * Base class for all modes of file connections. - * */ public static class FileRConnection extends BasePathRConnection { + private final boolean raw; + private final boolean internal; - public FileRConnection(String path, String modeString) throws IOException { - super(checkTemp(path), ConnectionClass.File, modeString); + public FileRConnection(String description, String path, String modeString, boolean blocking, String encoding, boolean raw, boolean internal) throws IOException { + super(description, checkTemp(path), ConnectionClass.File, modeString, blocking, encoding); + this.raw = raw; + this.internal = internal; openNonLazyConnection(); } @@ -72,194 +83,315 @@ public class FileConnections { } @Override + public boolean isInternal() { + return internal; + } + + @Override + @TruffleBoundary protected void createDelegateConnection() throws IOException { - DelegateRConnection delegate = null; - switch (getOpenMode().abstractOpenMode) { - case Read: - delegate = new FileReadTextRConnection(this); - break; - case Write: - delegate = new FileWriteTextRConnection(this, false); - break; - case Append: - delegate = new FileWriteTextRConnection(this, true); - break; - case ReadBinary: - delegate = new FileReadBinaryRConnection(this); - break; - case WriteBinary: - delegate = new FileWriteBinaryConnection(this, false); - break; - case ReadWriteTrunc: - case ReadWriteTruncBinary: - delegate = new FileReadWriteConnection(this); - break; - default: - throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + getOpenMode()); - } + + DelegateRConnection delegate = FileConnections.createDelegateConnection(this, RCompression.Type.NONE, raw); setDelegate(delegate); } } - static class FileReadTextRConnection extends DelegateReadRConnection implements ReadWriteHelper { - private InputStream inputStream; - - FileReadTextRConnection(BasePathRConnection base) throws IOException { - super(base); - // can be compressed - check for it - RCompression.Type cType = RCompression.getCompressionType(base.path); - switch (cType) { - case NONE: - inputStream = new BufferedInputStream(new FileInputStream(base.path)); - break; - case GZIP: - inputStream = new GZIPInputStream(new FileInputStream(base.path), CompressedConnections.GZIP_BUFFER_SIZE); - break; - case BZIP2: - // no in Java support, so go via byte array - byte[] bzipUdata = RCompression.bzipUncompressFromFile(base.path); - inputStream = new ByteArrayInputStream(bzipUdata); - break; - case XZ: - inputStream = new XZInputStream(new FileInputStream(base.path)); - break; - default: - throw RError.nyi(RError.SHOW_CALLER2, "compression type: " + cType.name()); - } + /** + * Base class for all modes of gzfile/bzfile/xzfile connections. N.B. In GNU R these can read + * gzip, bzip, lzma and uncompressed files, and this has to be implemented by reading the first + * few bytes of the file and detecting the type of the file. + */ + public static class CompressedRConnection extends BasePathRConnection { + private final RCompression.Type cType; + @SuppressWarnings("unused") private final int compression; // TODO + + public CompressedRConnection(String path, String modeString, Type cType, String encoding, int compression) throws IOException { + super(path, path, mapConnectionClass(cType), modeString, AbstractOpenMode.ReadBinary, encoding); + this.cType = cType; + this.compression = compression; + openNonLazyConnection(); } @Override - public int readBin(ByteBuffer buffer) throws IOException { - throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_READ_BINARY_CONNECTION); + @TruffleBoundary + protected void createDelegateConnection() throws IOException { + setDelegate(FileConnections.createDelegateConnection(this, cType, false)); + } - @Override - public byte[] readBinChars() throws IOException { - throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_READ_BINARY_CONNECTION); + // @Override + /** + * GnuR behavior for lazy connections is odd, e.g. gzfile returns "text", even though the + * default mode is "rb". + */ + // public boolean isTextMode() { + // } + } + + private static DelegateRConnection createUncompressedDelegateConnection(BasePathRConnection base) + throws IOException { + + DelegateRConnection delegate = null; + switch (base.getOpenMode().abstractOpenMode) { + case Read: + delegate = new FileReadTextRConnection(base); + break; + case ReadBinary: + delegate = new FileReadBinaryRConnection(base); + break; + case Write: + delegate = new FileWriteTextRConnection(base, false); + break; + case Append: + delegate = new FileWriteTextRConnection(base, true); + break; + case WriteBinary: + delegate = new FileWriteBinaryConnection(base, false); + break; + case ReadWriteTrunc: + delegate = new FileReadWriteTextConnection(base, false); + break; + case ReadWriteTruncBinary: + delegate = new FileReadWriteBinaryConnection(base, false); + break; + case ReadAppend: + delegate = new FileReadWriteTextConnection(base, true); + break; + case ReadAppendBinary: + delegate = new FileReadWriteBinaryConnection(base, true); + break; + default: + throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + base.getOpenMode()); + } + return delegate; + } + + private static DelegateRConnection createGZIPDelegateConnection(BasePathRConnection base) throws IOException { + + switch (base.getOpenMode().abstractOpenMode) { + case Read: + case ReadBinary: + return new CompressedInputRConnection(base, new GZIPInputStream(new FileInputStream(base.path), GZIP_BUFFER_SIZE)); + case Append: + case AppendBinary: + return new CompressedOutputRConnection(base, new GZIPOutputStream(new FileOutputStream(base.path, true), GZIP_BUFFER_SIZE), true); + case Write: + case WriteBinary: + return new CompressedOutputRConnection(base, new GZIPOutputStream(new FileOutputStream(base.path, false), GZIP_BUFFER_SIZE), true); + default: + throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + base.getOpenMode()); } + } - @TruffleBoundary - @Override - public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException { - return readLinesHelper(inputStream, n, warn, skipNul); + private static DelegateRConnection createXZDelegateConnection(BasePathRConnection base) throws IOException { + + switch (base.getOpenMode().abstractOpenMode) { + case Read: + case ReadBinary: + return new CompressedInputRConnection(base, new XZInputStream(new FileInputStream(base.path))); + case Append: + case AppendBinary: + return new CompressedOutputRConnection(base, new XZOutputStream(new FileOutputStream(base.path, true), new LZMA2Options(), XZ.CHECK_CRC32), false); + case Write: + case WriteBinary: + return new CompressedOutputRConnection(base, new XZOutputStream(new FileOutputStream(base.path, false), new LZMA2Options(), XZ.CHECK_CRC32), false); + default: + throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + base.getOpenMode()); } + } - @Override - public String readChar(int nchars, boolean useBytes) throws IOException { - return readCharHelper(nchars, inputStream, useBytes); + private static DelegateRConnection createBZIP2DelegateConnection(BasePathRConnection base) throws IOException { + + switch (base.getOpenMode().abstractOpenMode) { + case Read: + case ReadBinary: + byte[] bzipUdata = RCompression.bzipUncompressFromFile(base.path); + return new ByteStreamCompressedInputRConnection(base, new ByteArrayInputStream(bzipUdata)); + case Append: + case AppendBinary: + return new BZip2OutputRConnection(base, new ByteArrayOutputStream(), true); + case Write: + case WriteBinary: + return new BZip2OutputRConnection(base, new ByteArrayOutputStream(), false); + default: + throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + base.getOpenMode()); } + } - @Override - public InputStream getInputStream() throws IOException { - return inputStream; + @TruffleBoundary + private static DelegateRConnection createDelegateConnection(BasePathRConnection base, RCompression.Type cType, boolean raw) throws IOException { + AbstractOpenMode openMode = base.getOpenMode().abstractOpenMode; + + /* + * For input, we check the actual compression type as GNU R is permissive about the claimed + * type except 'raw' is true. + */ + final RCompression.Type cTypeActual; + if (!raw && (openMode == AbstractOpenMode.Read || openMode == AbstractOpenMode.ReadBinary)) { + cTypeActual = RCompression.getCompressionType(base.path); + if (cTypeActual != cType) { + base.updateConnectionClass(mapConnectionClass(cTypeActual)); + } + } else { + cTypeActual = cType; } - @Override - public void closeAndDestroy() throws IOException { - base.closed = true; - close(); + switch (cTypeActual) { + case NONE: + return createUncompressedDelegateConnection(base); + case GZIP: + return createGZIPDelegateConnection(base); + case XZ: + return createXZDelegateConnection(base); + case BZIP2: + return createBZIP2DelegateConnection(base); } + throw RInternalError.shouldNotReachHere("unsupported compression type"); + } - @Override - public void close() throws IOException { - inputStream.close(); + private static ConnectionClass mapConnectionClass(RCompression.Type cType) { + switch (cType) { + case NONE: + return ConnectionClass.File; + case GZIP: + return ConnectionClass.GZFile; + case BZIP2: + return ConnectionClass.BZFile; + case XZ: + return ConnectionClass.XZFile; + default: + throw RInternalError.shouldNotReachHere(); } } - private static class FileWriteTextRConnection extends DelegateWriteRConnection implements ReadWriteHelper { - private final BufferedOutputStream outputStream; + static class FileReadBinaryRConnection extends DelegateReadRConnection { + + private final FileChannel channel; - FileWriteTextRConnection(FileRConnection base, boolean append) throws IOException { + FileReadBinaryRConnection(BasePathRConnection base) throws IOException { super(base); - outputStream = new BufferedOutputStream(new FileOutputStream(base.path, append)); + channel = FileChannel.open(Paths.get(base.path), StandardOpenOption.READ); } @Override - public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException { - writeCharHelper(outputStream, s, pad, eos); + public boolean isSeekable() { + return true; } @Override - public void writeBin(ByteBuffer buffer) throws IOException { - throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_WRITE_BINARY_CONNECTION); + public long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { + return DelegateRConnection.seek(channel, offset, seekMode, seekRWMode); } @Override - public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException { - writeLinesHelper(outputStream, lines, sep); - flush(); + public ByteChannel getChannel() { + return channel; } - @Override - public void writeString(String s, boolean nl) throws IOException { - writeStringHelper(outputStream, s, nl); + } + + static class FileReadTextRConnection extends FileReadBinaryRConnection { + + FileReadTextRConnection(BasePathRConnection base) throws IOException { + super(base); } @Override - public OutputStream getOutputStream() throws IOException { - return outputStream; + public int readBin(ByteBuffer buffer) throws IOException { + throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_READ_BINARY_CONNECTION); } @Override - public void closeAndDestroy() throws IOException { - base.closed = true; - close(); + public byte[] readBinChars() throws IOException { + throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_READ_BINARY_CONNECTION); } + } - @Override - public void close() throws IOException { - outputStream.close(); + private static class FileWriteTextRConnection extends FileWriteBinaryConnection { + + FileWriteTextRConnection(BasePathRConnection base, boolean append) throws IOException { + super(base, append); } @Override - public void flush() throws IOException { - outputStream.flush(); + public void writeBin(ByteBuffer buffer) throws IOException { + throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_WRITE_BINARY_CONNECTION); } } - static class FileReadBinaryRConnection extends DelegateReadRConnection implements ReadWriteHelper { - private final FileInputStream inputStream; + private static class FileWriteBinaryConnection extends DelegateWriteRConnection { - FileReadBinaryRConnection(BasePathRConnection base) throws IOException { + private final FileChannel channel; + + FileWriteBinaryConnection(BasePathRConnection base, boolean append) throws IOException { super(base); - inputStream = new FileInputStream(base.path); + List<OpenOption> opts = new ArrayList<>(); + opts.add(StandardOpenOption.WRITE); + opts.add(StandardOpenOption.CREATE); + if (append) { + opts.add(StandardOpenOption.APPEND); + } else { + opts.add(StandardOpenOption.TRUNCATE_EXISTING); + } + channel = FileChannel.open(Paths.get(base.path), opts.toArray(new OpenOption[opts.size()])); } @Override - public String readChar(int nchars, boolean useBytes) throws IOException { - return readCharHelper(nchars, inputStream, useBytes); + public boolean isSeekable() { + return true; } @Override - public int readBin(ByteBuffer buffer) throws IOException { - return inputStream.getChannel().read(buffer); + protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { + return DelegateRConnection.seek(channel, offset, seekMode, seekRWMode); } @Override - public byte[] readBinChars() throws IOException { - return readBinCharsHelper(inputStream); + public ByteChannel getChannel() { + return channel; } - @TruffleBoundary @Override - public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException { - return readLinesHelper(inputStream, n, warn, skipNul); + public void truncate() throws IOException { + channel.truncate(channel.position()); } - @Override - public InputStream getInputStream() throws IOException { - return inputStream; + } + + private static class FileReadWriteTextConnection extends DelegateReadWriteRConnection { + + private final FileChannel channel; + private long readOffset; + private long writeOffset; + private SeekRWMode lastMode = SeekRWMode.READ; + + FileReadWriteTextConnection(BasePathRConnection base, boolean append) throws IOException { + super(base); + List<OpenOption> opts = new ArrayList<>(); + opts.add(StandardOpenOption.READ); + opts.add(StandardOpenOption.WRITE); + opts.add(StandardOpenOption.CREATE); + channel = FileChannel.open(Paths.get(base.path), opts.toArray(new OpenOption[opts.size()])); + if (append) { + writeOffset = channel.size(); + } else { + channel.truncate(0); + } } @Override - public void closeAndDestroy() throws IOException { - base.closed = true; - close(); + public int getc() throws IOException { + setReadPosition(); + final int value = super.readInternal(); + if (value != -1) { + readOffset++; + } + return value; } @Override - public void close() throws IOException { - inputStream.close(); + protected void updateReadOffset(int nBytesConsumed) { + readOffset += nBytesConsumed; } @Override @@ -268,83 +400,135 @@ public class FileConnections { } @Override - public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { - long position = inputStream.getChannel().position(); + protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { + long result; + boolean set = true; switch (seekMode) { case ENQUIRE: + set = false; + break; + case START: break; - case CURRENT: - if (offset != 0) { - inputStream.getChannel().position(position + offset); + default: + throw RError.nyi(RError.SHOW_CALLER, "seek mode"); + } + switch (seekRWMode) { + case LAST: + if (lastMode == SeekRWMode.READ) { + result = readOffset; + if (set) { + readOffset = offset; + } + } else { + result = writeOffset; + if (set) { + writeOffset = offset; + } } break; - case START: - inputStream.getChannel().position(offset); + case READ: + result = readOffset; + if (set) { + readOffset = offset; + } break; - case END: - throw RInternalError.unimplemented(); - + case WRITE: + result = writeOffset; + if (set) { + writeOffset = offset; + } + break; + default: + throw RError.nyi(RError.SHOW_CALLER, "seek mode"); } - return position; + return result; } - } - private static class FileWriteBinaryConnection extends DelegateWriteRConnection implements ReadWriteHelper { - private final FileOutputStream outputStream; + @Override + public String[] readLines(int n, boolean warn, boolean skipNul) throws IOException { + setReadPosition(); + return super.readLines(n, warn, skipNul); + } - FileWriteBinaryConnection(FileRConnection base, boolean append) throws IOException { - super(base); - outputStream = new FileOutputStream(base.path, append); + @Override + public int readBin(ByteBuffer buffer) throws IOException { + setReadPosition(); + return super.readBin(buffer); } @Override - public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException { - writeCharHelper(outputStream, s, pad, eos); + public String readChar(int nchars, boolean useBytes) throws IOException { + setReadPosition(); + return super.readChar(nchars, useBytes); } @Override - public void writeBin(ByteBuffer buffer) throws IOException { - outputStream.getChannel().write(buffer); + public byte[] readBinChars() throws IOException { + setReadPosition(); + return super.readBinChars(); } @Override - public OutputStream getOutputStream() throws IOException { - return outputStream; + public void close() throws IOException { + channel.close(); } @Override - public void closeAndDestroy() throws IOException { - base.closed = true; - close(); + public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException { + setWritePosition(); + super.writeLines(lines, sep, useBytes); + writeOffset = channel.position(); } @Override - public void close() throws IOException { - flush(); - outputStream.close(); + public void writeBin(ByteBuffer buffer) throws IOException { + setWritePosition(); + super.writeBin(buffer); } @Override - public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException { - for (int i = 0; i < lines.getLength(); i++) { - String line = lines.getDataAt(i); - outputStream.write(line.getBytes()); - outputStream.write(sep.getBytes()); - } + public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException { + setWritePosition(); + super.writeChar(s, pad, eos, useBytes); } @Override public void writeString(String s, boolean nl) throws IOException { - writeStringHelper(outputStream, s, nl); + setWritePosition(); + super.writeString(s, nl); + } + + @Override + public ByteChannel getChannel() { + return channel; + } + + private void setReadPosition() throws IOException { + if (lastMode != SeekRWMode.READ) { + channel.position(readOffset); + lastMode = SeekRWMode.READ; + } + } + + private void setWritePosition() throws IOException { + if (lastMode != SeekRWMode.WRITE) { + channel.position(writeOffset); + lastMode = SeekRWMode.WRITE; + } } @Override - public void flush() throws IOException { - outputStream.flush(); + public void truncate() throws IOException { + channel.truncate(writeOffset); + lastMode = SeekRWMode.WRITE; + // GnuR also freshly queries the file pointer. It may happen that the file pointer is + // different as expected. + writeOffset = channel.position(); } + } - private static class FileReadWriteConnection extends DelegateReadWriteRConnection implements ReadWriteHelper { + private static class FileReadWriteBinaryConnection extends DelegateReadWriteRConnection { /* * This is a minimal implementation to support one specific use in package installation. * @@ -356,52 +540,39 @@ public class FileConnections { private long readOffset; private long writeOffset; private SeekRWMode lastMode = SeekRWMode.READ; - private final RAFInputStream inputStream; - /** - * Allows an {@link RandomAccessFile} to appear to be an {@link InputStream}. - * - */ - private class RAFInputStream extends InputStream { - @Override - public int read() throws IOException { - return FileReadWriteConnection.this.getc(); - } - } - - FileReadWriteConnection(FileRConnection base) throws IOException { + FileReadWriteBinaryConnection(BasePathRConnection base, boolean append) throws IOException { super(base); - OpenMode openMode = base.getOpenMode(); - String rafMode = null; - switch (openMode.abstractOpenMode) { - case ReadWriteTrunc: - case ReadWriteTruncBinary: - rafMode = "rw"; - break; - default: - throw RInternalError.shouldNotReachHere(); + raf = new RandomAccessFile(base.path, "rw"); + if (append) { + writeOffset = raf.length(); + } else { + raf.setLength(0); } - raf = new RandomAccessFile(base.path, rafMode); - inputStream = new RAFInputStream(); } @Override public int getc() throws IOException { - raf.seek(readOffset); - int value = raf.read(); + setReadPosition(); + final int value = raf.read(); if (value != -1) { readOffset++; } return value; } + @Override + protected void updateReadOffset(int nBytesConsumed) { + readOffset += nBytesConsumed; + } + @Override public boolean isSeekable() { return true; } @Override - public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { + protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { long result = raf.getFilePointer(); switch (seekMode) { case ENQUIRE: @@ -430,25 +601,43 @@ public class FileConnections { } @Override - public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException { - raf.seek(readOffset); - return readLinesHelper(inputStream, n, warn, skipNul); + public String[] readLines(int n, boolean warn, boolean skipNul) throws IOException { + setReadPosition(); + return super.readLines(n, warn, skipNul); } @Override - public InputStream getInputStream() throws IOException { - return inputStream; + public int readBin(ByteBuffer buffer) throws IOException { + setReadPosition(); + return super.readBin(buffer); } @Override - public OutputStream getOutputStream() throws IOException { - throw RInternalError.unimplemented(); + public String readChar(int nchars, boolean useBytes) throws IOException { + setReadPosition(); + return super.readChar(nchars, useBytes); } @Override - public void closeAndDestroy() throws IOException { - base.closed = true; - close(); + public byte[] readBinChars() throws IOException { + setReadPosition(); + return super.readBinChars(); + } + + @TruffleBoundary + private void setReadPosition() throws IOException { + if (lastMode != SeekRWMode.READ) { + raf.seek(readOffset); + lastMode = SeekRWMode.READ; + } + } + + @TruffleBoundary + private void setWritePosition() throws IOException { + if (lastMode != SeekRWMode.WRITE) { + raf.seek(writeOffset); + lastMode = SeekRWMode.WRITE; + } } @Override @@ -458,52 +647,131 @@ public class FileConnections { @Override public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException { - // TODO encodings - raf.seek(writeOffset); - byte[] sepData = sep.getBytes(); - for (int i = 0; i < lines.getLength(); i++) { - writeString(lines.getDataAt(i), false); - raf.write(sepData); - } + setWritePosition(); + super.writeLines(lines, sep, useBytes); writeOffset = raf.getFilePointer(); - lastMode = SeekRWMode.WRITE; } @Override - public void flush() throws IOException { + public void writeBin(ByteBuffer buffer) throws IOException { + setWritePosition(); + super.writeBin(buffer); + } + + @Override + public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException { + setWritePosition(); + super.writeChar(s, pad, eos, useBytes); } @Override public void writeString(String s, boolean nl) throws IOException { - raf.write(s.getBytes()); - if (nl) { - raf.writeBytes(System.lineSeparator()); - } + setWritePosition(); + super.writeString(s, nl); } @Override - public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException { - throw RInternalError.unimplemented(); + public ByteChannel getChannel() { + return raf.getChannel(); } @Override - public String readChar(int nchars, boolean useBytes) throws IOException { - throw RInternalError.unimplemented(); + public void truncate() throws IOException { + raf.setLength(writeOffset); + lastMode = SeekRWMode.WRITE; + // GnuR also freshly queries the file pointer. It may happen that the file pointer is + // different as expected. + writeOffset = raf.getFilePointer(); + } + + } + + private static class CompressedInputRConnection extends DelegateReadRConnection { + private final ByteChannel channel; + + protected CompressedInputRConnection(BasePathRConnection base, InputStream is) { + super(base); + channel = ConnectionSupport.newChannel(is); } @Override - public void writeBin(ByteBuffer buffer) throws IOException { - throw RInternalError.unimplemented(); + public ByteChannel getChannel() { + return channel; } @Override - public int readBin(ByteBuffer buffer) throws IOException { - throw RInternalError.unimplemented(); + public boolean isSeekable() { + return false; + } + } + + private static class ByteStreamCompressedInputRConnection extends CompressedInputRConnection { + ByteStreamCompressedInputRConnection(BasePathRConnection base, ByteArrayInputStream is) { + super(base, is); + } + } + + private static class CompressedOutputRConnection extends DelegateWriteRConnection { + protected ByteChannel channel; + private final boolean seekable; + private long seekPosition = 0L; + + protected CompressedOutputRConnection(BasePathRConnection base, OutputStream os, boolean seekable) { + super(base); + this.seekable = seekable; + this.channel = ConnectionSupport.newChannel(os); } @Override - public byte[] readBinChars() throws IOException { - throw RInternalError.unimplemented(); + public void closeAndDestroy() throws IOException { + base.closed = true; + close(); + } + + @Override + protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { + if (seekable) { + // TODO GZIP is basically seekable; however, the output stream does not allow any + // seeking + long oldPos = seekPosition; + seekPosition = offset; + return oldPos; + } + return super.seek(offset, seekMode, seekRWMode); + } + + @Override + public boolean isSeekable() { + return seekable; + } + + @Override + public ByteChannel getChannel() { + return channel; + } + + @Override + public void truncate() throws IOException { + throw RError.nyi(RError.SHOW_CALLER, "truncating compressed file not"); + } + } + + private static class BZip2OutputRConnection extends CompressedOutputRConnection { + private final ByteArrayOutputStream bos; + private final boolean append; + + BZip2OutputRConnection(BasePathRConnection base, ByteArrayOutputStream os, boolean append) { + super(base, os, false); + this.bos = os; + this.append = append; + } + + @Override + public void close() throws IOException { + flush(); + // Now actually do the compression using sub-process + byte[] data = bos.toByteArray(); + RCompression.bzipCompressToFile(data, ((BasePathRConnection) base).path, append); } } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/NativeConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/NativeConnections.java new file mode 100644 index 0000000000000000000000000000000000000000..e6e7baa075ac51bb6514218b5179082d3684e111 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/NativeConnections.java @@ -0,0 +1,348 @@ +/* + * 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 + * 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.runtime.conn; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ByteChannel; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import com.oracle.truffle.api.RootCallTarget; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass; +import com.oracle.truffle.r.runtime.conn.RConnection.SeekMode; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.RExternalPtr; +import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.ffi.CallRFFI; +import com.oracle.truffle.r.runtime.ffi.DLL; +import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; +import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; + +/** + * Represents a custom connection created in native code and having its own native read and write + * functions. + */ +public class NativeConnections { + + private static final String OPEN_NATIVE_CONNECTION = "__OpenNativeConnection"; + private static final String CLOSE_NATIVE_CONNECTION = "__CloseNativeConnection"; + private static final String READ_NATIVE_CONNECTION = "__ReadNativeConnection"; + private static final String WRITE_NATIVE_CONNECTION = "__WriteNativeConnection"; + private static final String GET_FLAG_NATIVE_CONNECTION = "__GetFlagNativeConnection"; + private static final String SEEK_NATIVE_CONNECTION = "__SeekNativeConnection"; + + private static final Map<String, NativeCallInfo> callInfoTable = new HashMap<>(4); + + private static NativeCallInfo getNativeFunctionInfo(String name) { + NativeCallInfo nativeCallInfo = callInfoTable.get(name); + if (nativeCallInfo == null) { + DLLInfo findLibraryContainingSymbol = DLL.findLibraryContainingSymbol(name); + SymbolHandle findSymbol = DLL.findSymbol(name, findLibraryContainingSymbol); + nativeCallInfo = new NativeCallInfo(name, findSymbol, findLibraryContainingSymbol); + callInfoTable.put(name, nativeCallInfo); + } + return nativeCallInfo; + } + + public static class NativeRConnection extends BaseRConnection { + private final String customConClass; + private final String description; + private final RExternalPtr addr; + + public NativeRConnection(String description, String modeString, String customConClass, RExternalPtr addr) throws IOException { + super(ConnectionClass.NATIVE, modeString, AbstractOpenMode.Read); + this.customConClass = Objects.requireNonNull(customConClass); + this.description = Objects.requireNonNull(description); + this.addr = addr; + } + + @Override + protected void createDelegateConnection() throws IOException { + DelegateRConnection delegate = null; + switch (getOpenMode().abstractOpenMode) { + case Read: + case ReadBinary: + delegate = new ReadNativeConnection(this); + break; + case Write: + case WriteBinary: + delegate = new WriteNativeConnection(this); + break; + case ReadWrite: + case ReadWriteBinary: + case ReadWriteTrunc: + case ReadWriteTruncBinary: + delegate = new ReadWriteNativeConnection(this); + break; + + } + setDelegate(delegate); + } + + @Override + public String getSummaryDescription() { + return description; + } + + @Override + public String getConnectionClass() { + return customConClass; + } + + public RExternalPtr getNativeAddress() { + return addr; + } + + @Override + public boolean canRead() { + return getFlag("canread"); + } + + @Override + public boolean canWrite() { + return getFlag("canwrite"); + } + + public boolean getFlag(String name) { + NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(GET_FLAG_NATIVE_CONNECTION); + RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget(); + + Object result = nativeCallTarget.call(ni, new Object[]{addr, name}); + if (result instanceof RLogicalVector) { + return ((RLogicalVector) result).getDataAt(0) == RRuntime.LOGICAL_TRUE; + } + throw new RInternalError("could not get value of flag " + name); + } + } + + /** + * @param addr Native address of the Rconnection data structure. + * @param offset seek offset + * @param seekMode seek anchor + * @param rw seek mode (read=1, write=2, last) + * @return the old cursor position + */ + private static long seekSingleMode(RExternalPtr addr, long offset, SeekMode seekMode, int rw) { + RDoubleVector where = RDataFactory.createDoubleVectorFromScalar(offset); + RIntVector seekCode; + switch (seekMode) { + case CURRENT: + seekCode = RDataFactory.createIntVectorFromScalar(1); + break; + case END: + seekCode = RDataFactory.createIntVectorFromScalar(2); + break; + case START: + seekCode = RDataFactory.createIntVectorFromScalar(0); + break; + default: + seekCode = RDataFactory.createIntVectorFromScalar(-1); + break; + } + RIntVector rwCode = RDataFactory.createIntVectorFromScalar(rw); + + NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(SEEK_NATIVE_CONNECTION); + RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget(); + Object result = nativeCallTarget.call(ni, new Object[]{addr, where, seekCode, rwCode}); + if (result instanceof RDoubleVector) { + return (long) ((RDoubleVector) result).getDataAt(0); + } + throw RInternalError.shouldNotReachHere("unexpected result type"); + } + + static class ReadNativeConnection extends DelegateReadRConnection { + + private final ByteChannel ch; + private final boolean seekable; + + protected ReadNativeConnection(NativeRConnection base) throws IOException { + super(base, 4096); + ch = new NativeChannel(base); + NativeConnections.openNative(base.addr); + + // In theory, the flag could change any time, but this makes no sense. + seekable = base.getFlag("canseek"); + } + + @Override + public ByteChannel getChannel() throws IOException { + return ch; + } + + @Override + protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { + // seek mode read -> rw = 1 + return seekSingleMode(((NativeRConnection) base).addr, offset, seekMode, 1); + } + + @Override + public boolean isSeekable() { + return seekable; + } + } + + static class WriteNativeConnection extends DelegateWriteRConnection { + + private final ByteChannel ch; + private final boolean seekable; + + protected WriteNativeConnection(NativeRConnection base) throws IOException { + super(base); + ch = new NativeChannel(base); + NativeConnections.openNative(base.addr); + + // In theory, the flag could change any time, but this makes no sense. + seekable = base.getFlag("canseek"); + } + + @Override + public ByteChannel getChannel() throws IOException { + return ch; + } + + @Override + protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { + // seek mode write -> rw = 2 + return seekSingleMode(((NativeRConnection) base).addr, offset, seekMode, 2); + } + + @Override + public boolean isSeekable() { + return seekable; + } + } + + static class ReadWriteNativeConnection extends DelegateWriteRConnection { + + private final ByteChannel ch; + private final boolean seekable; + private int lastSeekMode = 1; + + protected ReadWriteNativeConnection(NativeRConnection base) throws IOException { + super(base); + ch = new NativeChannel(base); + NativeConnections.openNative(base.addr); + + // In theory, the flag could change any time, but this makes no sense. + seekable = base.getFlag("canseek"); + } + + @Override + public ByteChannel getChannel() throws IOException { + return ch; + } + + @Override + protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { + int rwMode; + switch (seekRWMode) { + case READ: + rwMode = 1; + break; + case WRITE: + rwMode = 2; + break; + default: + rwMode = lastSeekMode; + + } + lastSeekMode = rwMode; + return seekSingleMode(((NativeRConnection) base).addr, offset, seekMode, rwMode); + } + + @Override + public boolean isSeekable() { + return seekable; + } + } + + private static void openNative(RExternalPtr addr) throws IOException { + NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(OPEN_NATIVE_CONNECTION); + RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget(); + + Object result = nativeCallTarget.call(ni, new Object[]{addr}); + if (!(result instanceof RLogicalVector && ((RLogicalVector) result).getDataAt(0) == RRuntime.LOGICAL_TRUE)) { + throw new IOException("could not open connection"); + } + } + + private static class NativeChannel implements ByteChannel { + + private final NativeRConnection base; + + NativeChannel(NativeRConnection base) { + this.base = base; + } + + @Override + public int read(ByteBuffer dst) throws IOException { + NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(READ_NATIVE_CONNECTION); + RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget(); + Object call = nativeCallTarget.call(ni, new Object[]{base.addr, dst.array(), dst.remaining()}); + + if (call instanceof RIntVector) { + int nread = ((RIntVector) call).getDataAt(0); + // update buffer's position ! + dst.position(nread); + return nread; + } + + throw RInternalError.shouldNotReachHere("unexpected result type"); + } + + @Override + public boolean isOpen() { + return true; + } + + @Override + public void close() throws IOException { + NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(CLOSE_NATIVE_CONNECTION); + RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget(); + nativeCallTarget.call(ni, new Object[]{base.addr}); + } + + @Override + public int write(ByteBuffer src) throws IOException { + NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(WRITE_NATIVE_CONNECTION); + RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget(); + + Object result = nativeCallTarget.call(ni, new Object[]{base.addr, src.array(), src.remaining()}); + + if (result instanceof RIntVector) { + return ((RIntVector) result).getDataAt(0); + } + + throw RInternalError.shouldNotReachHere("unexpected result type"); + } + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java new file mode 100644 index 0000000000000000000000000000000000000000..8aa871b1b29f22629d12022f1a37493da5a01970 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java @@ -0,0 +1,189 @@ +/* + * 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 + * 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.runtime.conn; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.ProcessBuilder.Redirect; +import java.nio.ByteBuffer; +import java.nio.channels.ByteChannel; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; + +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass; + +public class PipeConnections { + + private static Process executeAndJoin(String command) throws IOException { + ProcessBuilder pb = new ProcessBuilder("/bin/sh", "-c", command); + pb.redirectError(Redirect.INHERIT); + Process p = pb.start(); + try { + p.waitFor(); + } catch (InterruptedException e) { + // TODO not sure how to handle an interrupted exception at this point + } + return p; + } + + public static class PipeRConnection extends BaseRConnection { + + private final String command; + + public PipeRConnection(String command, String open, String encoding) throws IOException { + super(ConnectionClass.FIFO, open, AbstractOpenMode.Read, encoding); + this.command = command; + openNonLazyConnection(); + } + + @Override + protected void createDelegateConnection() throws IOException { + final DelegateRConnection delegate; + switch (getOpenMode().abstractOpenMode) { + case Read: + case ReadBinary: + delegate = new PipeReadRConnection(this, command); + break; + case Write: + case WriteBinary: + delegate = new PipeWriteConnection(this, command); + break; + case ReadAppend: + case ReadWrite: + case ReadWriteBinary: + case ReadWriteTrunc: + case ReadWriteTruncBinary: + delegate = new PipeReadWriteConnection(this, command); + break; + default: + throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + getOpenMode()); + } + setDelegate(delegate); + } + + @Override + public String getSummaryDescription() { + return command; + } + } + + static class PipeReadRConnection extends DelegateReadRConnection { + private final ByteChannel channel; + + protected PipeReadRConnection(BaseRConnection base, String command) throws IOException { + super(base); + Process p = PipeConnections.executeAndJoin(command); + channel = ConnectionSupport.newChannel(p.getInputStream()); + } + + @Override + public ByteChannel getChannel() { + return channel; + } + + @Override + public boolean isSeekable() { + return false; + } + } + + private static class PipeWriteConnection extends DelegateWriteRConnection { + private final ByteChannel channel; + + PipeWriteConnection(BaseRConnection base, String command) throws IOException { + super(base); + Process p = PipeConnections.executeAndJoin(command); + channel = ConnectionSupport.newChannel(p.getOutputStream()); + } + + @Override + public ByteChannel getChannel() { + return channel; + } + + @Override + public boolean isSeekable() { + return false; + } + } + + private static class PipeReadWriteConnection extends DelegateReadWriteRConnection { + + private final RWChannel channel; + + protected PipeReadWriteConnection(BaseRConnection base, String command) throws IOException { + super(base); + Process p = PipeConnections.executeAndJoin(command); + channel = new RWChannel(p.getInputStream(), p.getOutputStream()); + } + + @Override + public ByteChannel getChannel() { + return channel; + } + + @Override + public boolean isSeekable() { + return false; + } + + private static final class RWChannel implements ByteChannel { + private final ReadableByteChannel rchannel; + private final WritableByteChannel wchannel; + + RWChannel(InputStream in, OutputStream out) { + rchannel = Channels.newChannel(in); + wchannel = Channels.newChannel(out); + } + + @Override + public int read(ByteBuffer dst) throws IOException { + return rchannel.read(dst); + } + + @Override + public boolean isOpen() { + return rchannel.isOpen() && wchannel.isOpen(); + } + + @Override + public void close() throws IOException { + rchannel.close(); + wchannel.close(); + } + + @Override + public int write(ByteBuffer src) throws IOException { + return wchannel.write(src); + } + + } + + } + +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java index b699372ccaae032d19a0777b141c5d47ba662ce7..df7d420c8b6200f86b2afaa6d244e1e3bfef8c1c 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.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 @@ -26,156 +26,65 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; -import java.util.LinkedList; +import java.nio.channels.ByteChannel; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection; import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.RAttributesLayout; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RExternalPtr; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.RTruffleObject; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; /** * Denotes an R {@code connection} instance used in the {@code base} I/O library. - * - * TODO Refactor the pushBack code into ConnectionsSupport */ -public abstract class RConnection implements AutoCloseable { - - public final RAbstractIntVector asVector() { - String[] classes = new String[]{ConnectionSupport.getBaseConnection(this).getConnectionClass().getPrintName(), "connection"}; - - RAbstractIntVector result = RDataFactory.createIntVector(new int[]{getDescriptor()}, true); - - RStringVector classVector = RDataFactory.createStringVector(classes, RDataFactory.COMPLETE_VECTOR); - // it's important to put "this" into the externalptr, so that it doesn't get collected - RExternalPtr connectionId = RDataFactory.createExternalPtr(null, this, RDataFactory.createSymbol("connection"), RNull.instance); - DynamicObject attrs = RAttributesLayout.createClassWithConnId(classVector, connectionId); - result.initAttributes(attrs); - return result; - } +public interface RConnection extends AutoCloseable, RTruffleObject { - public static BaseRConnection fromIndex(int con) { + static BaseRConnection fromIndex(int con) { return RContext.getInstance().stateRConnection.getConnection(con, true); } - private LinkedList<String> pushBack; - - public abstract String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException; - - private String readOneLineWithPushBack(String[] res, int ind, @SuppressWarnings("unused") boolean warn, @SuppressWarnings("unused") boolean skipNul) { - String s = pushBack.pollLast(); - if (s == null) { - return null; - } else { - String[] lines = s.split("\n", 2); - if (lines.length == 2) { - // we hit end of the line - if (lines[1].length() != 0) { - // suffix is not empty and needs to be processed later - pushBack.push(lines[1]); - } - res[ind] = lines[0]; - return null; - } else { - // no end of the line found yet - StringBuilder sb = new StringBuilder(); - do { - assert lines.length == 1; - sb.append(lines[0]); - s = pushBack.pollLast(); - if (s == null) { - break; - } - - lines = s.split("\n", 2); - if (lines.length == 2) { - // we hit end of the line - if (lines[1].length() != 0) { - // suffix is not empty and needs to be processed later - pushBack.push(lines[1]); - } - res[ind] = sb.append(lines[0]).toString(); - return null; - } // else continue - } while (true); - return sb.toString(); - } - } - } - - @TruffleBoundary - private String[] readLinesWithPushBack(int n, boolean warn, boolean skipNul) throws IOException { - String[] res = new String[n]; - for (int i = 0; i < n; i++) { - String s = readOneLineWithPushBack(res, i, warn, skipNul); - if (s == null) { - if (res[i] == null) { - // no more push back value - System.arraycopy(readLinesInternal(n - i, warn, skipNul), 0, res, i, n - i); - pushBack = null; - break; - } - // else res[i] has been filled - move to trying to fill the next one - } else { - // reached the last push back value without reaching and of line - assert pushBack.size() == 0; - System.arraycopy(readLinesInternal(n - i, warn, skipNul), 0, res, i, n - i); - res[i] = s + res[i]; - pushBack = null; - break; - } - } - return res; - } - /** - * Read (n > 0 up to n else unlimited) lines on the connection. + * Return the underlying input stream (for internal use).<br> + * <p> + * <b>NOTE:</b> The connection may do some caching internally! Therefore, the behavior is + * undefined if you mix using the input stream directly and using the read methods of the + * connection. + * </p> * */ - @TruffleBoundary - public String[] readLines(int n, boolean warn, boolean skipNul) throws IOException { - if (pushBack == null) { - return readLinesInternal(n, warn, skipNul); - } else if (pushBack.size() == 0) { - pushBack = null; - return readLinesInternal(n, warn, skipNul); - } else { - return readLinesWithPushBack(n, warn, skipNul); - } - } + InputStream getInputStream() throws IOException; /** - * Return the underlying input stream (for internal use). TODO Replace with a more principled - * solution. + * Return the underlying output stream (for internal use).<br> + * <p> + * <b>NOTE:</b> The connection may do some caching internally! Therefore, the behavior is + * undefined if you mix using the output stream directly and using the write methods of the + * connection. + * </p> */ - public abstract InputStream getInputStream() throws IOException; + OutputStream getOutputStream() throws IOException; /** - * Return the underlying output stream (for internal use). TODO Replace with a more principled - * solution. + * Return the underlying byte channel (for internal use). + * + * @throws IOException */ - public abstract OutputStream getOutputStream() throws IOException; + ByteChannel getChannel() throws IOException; /** * Close the connection. The corresponds to the {@code R close} function. */ - public abstract void closeAndDestroy() throws IOException; + void closeAndDestroy() throws IOException; /** * Returns {@ode true} iff we can read on this connection. */ - public abstract boolean canRead(); + boolean canRead(); /** * Returns {@ode true} iff we can write on this connection. */ - public abstract boolean canWrite(); + boolean canWrite(); /** * Forces the connection open. If the connection was already open does nothing. Otherwise, tries @@ -198,56 +107,23 @@ public abstract class RConnection implements AutoCloseable { * rely on it but should use the result in the body of the {@code try} block. If the connection * cannot be opened {@link IOException} is thrown. */ - public abstract RConnection forceOpen(String modeString) throws IOException; + RConnection forceOpen(String modeString) throws IOException; /** * Closes the internal state of the stream, but does not set the connection state to "closed", * i.e., allowing it to be re-opened. */ @Override - public abstract void close() throws IOException; - - /** - * Pushes lines back to the connection. - */ - @TruffleBoundary - public final void pushBack(RAbstractStringVector lines, boolean addNewLine) { - if (pushBack == null) { - pushBack = new LinkedList<>(); - } - for (int i = 0; i < lines.getLength(); i++) { - String newLine = lines.getDataAt(i); - if (addNewLine) { - newLine = newLine + '\n'; - } - pushBack.addFirst(newLine); - } - } - - /** - * Return the length of the push back. - */ - @TruffleBoundary - public final int pushBackLength() { - return pushBack == null ? 0 : pushBack.size(); - } - - /** - * Clears the pushback. - */ - @TruffleBoundary - public final void pushBackClear() { - pushBack = null; - } + void close() throws IOException; - public enum SeekMode { + enum SeekMode { ENQUIRE, START, CURRENT, END } - public enum SeekRWMode { + enum SeekRWMode { LAST, READ, WRITE @@ -256,27 +132,30 @@ public abstract class RConnection implements AutoCloseable { /** * Support for {@code isSeekable} Internal. */ - public abstract boolean isSeekable(); + boolean isSeekable(); /** - * Support for {@code seek} Internal. + * Allows to seek in the connection. */ - public abstract long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException; + long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException; /** - * Internal support for reading one character at a time. + * Internal support for reading one byte at a time.<br> + * <p> + * <b>NOTE:</b> This method is also used from native code. Do not change the signature! + * </p> */ - public abstract int getc() throws IOException; + int getc() throws IOException; /** * Write the {@code lines} to the connection, with {@code sep} appended after each "line". N.B. * The output will only appear as a sequence of lines if {@code sep == "\n"}. */ - public abstract void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException; + void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException; - public abstract void flush() throws IOException; + void flush() throws IOException; - public abstract int getDescriptor(); + int getDescriptor(); /** * Writes {@code s} optionally followed by a newline to the connection. This does not correspond @@ -284,7 +163,7 @@ public abstract class RConnection implements AutoCloseable { * Since these can be diverted by the {@code sink} builtin, every output connection class must * support this. */ - public abstract void writeString(String s, boolean nl) throws IOException; + void writeString(String s, boolean nl) throws IOException; /** * Internal connection-specific support for the {@code writeChar} builtin. @@ -292,22 +171,22 @@ public abstract class RConnection implements AutoCloseable { * @param s string to output * @param pad number of (zero) pad bytes * @param eos string to append to s - * @param useBytes TODO + * @param useBytes */ - public abstract void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException; + void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException; /** * Internal connection-specific support for the {@code readChar} builtin. * * @param nchars number of characters to read */ - public abstract String readChar(int nchars, boolean useBytes) throws IOException; + String readChar(int nchars, boolean useBytes) throws IOException; /** * Internal connection-specific support for the {@code writeBin} builtin. The implementation * should attempt to write all the data, denoted by {@code buffer.remaining()}. */ - public abstract void writeBin(ByteBuffer buffer) throws IOException; + void writeBin(ByteBuffer buffer) throws IOException; /** * Internal connection-specific support for the {@code readBin} builtin. The buffer is allocated @@ -315,7 +194,7 @@ public abstract class RConnection implements AutoCloseable { * should attempt to read that much data, returning the actual number read as the result. EOS is * denoted by a return value of zero. */ - public abstract int readBin(ByteBuffer buffer) throws IOException; + int readBin(ByteBuffer buffer) throws IOException; /** * Internal connection-specific support for the {@code readBin} builtin on character data. @@ -324,16 +203,28 @@ public abstract class RConnection implements AutoCloseable { * implies that no data was read. The caller must locate the null terminator to determine the * length of the string. */ - public abstract byte[] readBinChars() throws IOException; + byte[] readBinChars() throws IOException; + + /** + * Read (n > 0 up to n else unlimited) lines on the connection. + */ + @TruffleBoundary + String[] readLines(int n, boolean warn, boolean skipNul) throws IOException; /** * Returns {@code true} iff this is a text mode connection. */ - public abstract boolean isTextMode(); + boolean isTextMode(); /** * Returns {@code true} iff this connection is open. */ - public abstract boolean isOpen(); + boolean isOpen(); + + /** + * Truncates the connection (if possible). + */ + void truncate() throws IOException; + void pushBack(RAbstractStringVector lines, boolean addNewLine); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java new file mode 100644 index 0000000000000000000000000000000000000000..3abb2e1bca5d47ddbe3ca820d2d6bd4952a22cde --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java @@ -0,0 +1,239 @@ +/* + * 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 + * 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.runtime.conn; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.SeekableByteChannel; +import java.util.Objects; + +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection; +import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass; + +public class RawConnections { + + public static class RawRConnection extends BaseRConnection { + + private final SeekableMemoryByteChannel channel; + private final String description; + + public RawRConnection(String description, byte[] dataTemp, String open) throws IOException { + super(ConnectionClass.RAW, open, AbstractOpenMode.Read); + this.channel = new SeekableMemoryByteChannel(dataTemp); + this.description = description; + openNonLazyConnection(); + } + + @Override + protected void createDelegateConnection() throws IOException { + DelegateRConnection delegate = null; + switch (getOpenMode().abstractOpenMode) { + case Read: + case ReadBinary: + delegate = new RawReadRConnection(this, channel); + break; + case Write: + case WriteBinary: + delegate = new RawWriteBinaryConnection(this, channel, false); + break; + case Append: + delegate = new RawWriteBinaryConnection(this, channel, true); + break; + case ReadAppend: + delegate = new RawReadWriteConnection(this, channel, true); + break; + case ReadWrite: + case ReadWriteBinary: + case ReadWriteTrunc: + case ReadWriteTruncBinary: + delegate = new RawReadWriteConnection(this, channel, false); + break; + default: + throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + getOpenMode()); + } + setDelegate(delegate); + } + + @Override + public String getSummaryDescription() { + return description; + } + + @Override + public String getSummaryText() { + return "binary"; + } + + public byte[] getValue() { + return channel.getBuffer(); + } + + private static long seek(SeekableByteChannel channel, long offset, SeekMode seekMode, @SuppressWarnings("unused") SeekRWMode seekRWMode) throws IOException { + final long origPos = channel.position(); + final long newPos; + switch (seekMode) { + case START: + newPos = offset; + break; + case CURRENT: + newPos = origPos + offset; + break; + default: + throw RError.nyi(RError.SHOW_CALLER, "seek mode"); + } + if (newPos >= 0L && newPos <= channel.size()) { + channel.position(newPos); + } else { + throw RError.error(RError.SHOW_CALLER, RError.Message.SEEK_OUTSITE_RAW_CONNECTION); + } + return origPos; + } + + } + + static class RawReadRConnection extends DelegateReadRConnection { + private SeekableMemoryByteChannel channel; + + RawReadRConnection(BaseRConnection base, SeekableMemoryByteChannel channel) { + super(base, 0); + this.channel = channel; + try { + channel.position(0L); + } catch (IOException e) { + RInternalError.shouldNotReachHere(); + } + } + + RawReadRConnection(BaseRConnection base) { + super(base); + } + + @Override + public byte[] readBinChars() throws IOException { + // acquire copy from buffer without advancing the cursorskipNul + final byte[] buffer = channel.getBufferFromCursor(); + int i = 0; + while (i < buffer.length && buffer[i] != (byte) 0) { + i++; + } + if (i < buffer.length) { + ByteBuffer readBuf = ByteBuffer.allocate(i + 1); + channel.read(readBuf); + return readBuf.array(); + } + return new byte[0]; + } + + @Override + public long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { + return RawRConnection.seek(channel, offset, seekMode, seekRWMode); + } + + @Override + public SeekableByteChannel getChannel() { + return channel; + } + + @Override + public boolean isSeekable() { + return true; + } + } + + private static class RawWriteBinaryConnection extends DelegateWriteRConnection { + private final SeekableMemoryByteChannel channel; + + RawWriteBinaryConnection(BaseRConnection base, SeekableMemoryByteChannel channel, boolean append) { + super(base); + this.channel = Objects.requireNonNull(channel); + if (!append) { + try { + channel.position(0); + } catch (IOException e) { + RInternalError.shouldNotReachHere(); + } + } + } + + @Override + protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { + return RawRConnection.seek(channel, offset, seekMode, seekRWMode); + } + + @Override + public SeekableByteChannel getChannel() { + return channel; + } + + @Override + public boolean isSeekable() { + return true; + } + + @Override + public void truncate() throws IOException { + channel.truncate(channel.position()); + } + } + + private static class RawReadWriteConnection extends DelegateReadWriteRConnection { + + private final SeekableMemoryByteChannel channel; + + protected RawReadWriteConnection(BaseRConnection base, SeekableMemoryByteChannel channel, boolean append) { + super(base, 0); + this.channel = channel; + if (append) { + try { + channel.position(channel.size()); + } catch (IOException e) { + RInternalError.shouldNotReachHere(); + } + } + } + + @Override + protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { + return RawRConnection.seek(channel, offset, seekMode, seekRWMode); + } + + @Override + public SeekableByteChannel getChannel() { + return channel; + } + + @Override + public boolean isSeekable() { + return true; + } + + @Override + public void truncate() throws IOException { + channel.truncate(channel.position()); + } + } + +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java new file mode 100644 index 0000000000000000000000000000000000000000..7476dc54267c8089785ea1fdb99c401363d34367 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java @@ -0,0 +1,281 @@ +/* + * 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 + * 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.runtime.conn; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.SeekableByteChannel; +import java.util.Arrays; +import java.util.Objects; + +import com.oracle.truffle.r.runtime.RInternalError; + +/** + * A resizable byte channel backed by a byte array. + */ +public class SeekableMemoryByteChannel implements SeekableByteChannel { + + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + + /** Current cursor position. */ + private long position = 0L; + + /** Position of the last available byte (exclusive). */ + private long endPos = 0L; + + private long offset = 0L; + private byte[] buf; + private boolean open = true; + + public SeekableMemoryByteChannel(int initialCapacity) { + if (initialCapacity < 0) { + throw new IllegalArgumentException("'initialCapacity' must not be negative"); + } + buf = new byte[initialCapacity]; + } + + /** + * Find next power of two (see Hacker's Delight). + * + * @param n the number + */ + private static int clp2(final int n) { + int x = n; + x = x - 1; + x = x | (x >> 1); + x = x | (x >> 2); + x = x | (x >> 4); + x = x | (x >> 8); + x = x | (x >> 16); + return x + 1; + } + + public byte[] getBufferFromCursor() { + return Arrays.copyOfRange(buf, (int) (position - offset), (int) (endPos - offset)); + } + + public byte[] getBuffer() { + return Arrays.copyOfRange(buf, (int) offset, (int) (endPos - offset)); + } + + public SeekableMemoryByteChannel() { + this(32); + } + + public SeekableMemoryByteChannel(byte[] initialBuffer) { + this(clp2(Objects.requireNonNull(initialBuffer).length)); + assert buf.length >= initialBuffer.length; + endPos = initialBuffer.length; + position = 0L; + System.arraycopy(initialBuffer, 0, buf, 0, initialBuffer.length); + } + + @Override + public boolean isOpen() { + return open; + } + + @Override + public int read(ByteBuffer dst) throws IOException { + if (!open) { + throw new ClosedChannelException(); + } + Objects.requireNonNull(dst); + RInternalError.guarantee(dst.remaining() <= Integer.MAX_VALUE); + final int nCanRead = (int) Math.min(dst.remaining(), remaining()); + dst.put(buf, (int) (position - offset), nCanRead); + position += nCanRead; + assert position <= endPos; + return nCanRead; + } + + @Override + public int write(ByteBuffer src) throws IOException { + if (!open) { + throw new ClosedChannelException(); + } + Objects.requireNonNull(src); + final int len = src.remaining(); + ensureCapacity((int) (position - offset + len)); + src.get(buf, (int) (position - offset), len); + position += len; + endPos = Math.max(position, endPos); + return len; + } + + public int write(byte[] data) throws IOException { + if (!open) { + throw new ClosedChannelException(); + } + Objects.requireNonNull(data); + ensureCapacity((int) (position - offset + data.length)); + System.arraycopy(data, 0, buf, (int) (position - offset), data.length); + position += data.length; + endPos = Math.max(position, endPos); + return data.length; + } + + public void write(int b) throws IOException { + // this is probably bad, but duplicating code is also bad and this case is probably + // rarely used + write(new byte[]{(byte) b}); + } + + private void ensureCapacity(int minCapacity) { + // borrowed from ByteArrayOutputStream + if (minCapacity - buf.length > 0) { + grow(minCapacity); + } + } + + private void grow(int minCapacity) { + // borrowed from ByteArrayOutputStream + int oldCapacity = buf.length; + int newCapacity = oldCapacity << 1; + if (newCapacity - minCapacity < 0) { + newCapacity = minCapacity; + } + if (newCapacity - MAX_ARRAY_SIZE > 0) { + newCapacity = hugeCapacity(minCapacity); + } + buf = Arrays.copyOf(buf, newCapacity); + } + + private static int hugeCapacity(int minCapacity) { + // borrowed from ByteArrayOutputStream + if (minCapacity < 0) { + throw new OutOfMemoryError(); + } + return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; + } + + @Override + public long position() throws IOException { + return position; + } + + @Override + public long size() { + return endPos - offset; + } + + private long remaining() { + return endPos - position; + } + + @Override + public SeekableByteChannel position(long newPosition) throws IOException { + if (newPosition < 0) { + throw new IllegalArgumentException("newPosition must not be negative"); + } + if (newPosition + offset > endPos) { + throw new IllegalArgumentException("setting position outside data range is currently not supported"); + } + position = newPosition + offset; + return this; + } + + @Override + public SeekableByteChannel truncate(long size) throws IOException { + if (size < 0) { + throw new IllegalArgumentException("'size' cannot be negative"); + } + + // avoid security leak by nulling previous data + final int from; + final int to; + if (size < endPos) { + from = (int) (size - offset); + to = (int) (endPos - offset); + } else { + to = (int) (size - offset); + from = (int) (endPos - offset); + + // need to enlarge buffer + ensureCapacity(to); + } + Arrays.fill(buf, from, to, (byte) 0); + + position = Math.min(position, size); + endPos = size; + return this; + } + + @Override + public void close() throws IOException { + setOpen(false); + } + + public void setOpen(boolean open) { + this.open = open; + } + + public InputStream getInputStream() { + return new SyncIS(); + } + + private class SyncIS extends InputStream { + + @Override + public int read() throws IOException { + return SeekableMemoryByteChannel.this.read(); + } + + } + + public OutputStream getOutputStream() { + return new SyncOS(); + } + + public int read() throws IOException { + if (position < endPos) { + final ByteBuffer bf = ByteBuffer.allocate(1); + read(bf); + bf.rewind(); + return bf.get(); + } + return -1; + } + + private class SyncOS extends OutputStream { + + @Override + public void write(int b) throws IOException { + SeekableMemoryByteChannel.this.write(b); + } + + @Override + public void write(byte[] b) throws IOException { + SeekableMemoryByteChannel.this.write(b); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + SeekableMemoryByteChannel.this.write(ByteBuffer.wrap(b, off, len)); + } + } + +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java index e7da9ceca6c5ac57c0273d57c0c631a8dc9898e9..ae41e53ce740f8924db0cc2d87bc7e1fec5c64cd 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java @@ -23,21 +23,16 @@ package com.oracle.truffle.r.runtime.conn; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.net.InetSocketAddress; -import java.net.ServerSocket; import java.net.Socket; -import java.nio.ByteBuffer; +import java.nio.channels.ByteChannel; +import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode; import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection; import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadWriteRConnection; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ReadWriteHelper; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; public class SocketConnections { /** @@ -50,22 +45,30 @@ public class SocketConnections { protected final boolean server; protected final String host; protected final int port; - protected final boolean blocking; protected final int timeout; - public RSocketConnection(String modeString, boolean server, String host, int port, boolean blocking, int timeout) throws IOException { - super(ConnectionClass.Socket, modeString, AbstractOpenMode.Read); + public RSocketConnection(String modeString, boolean server, String host, int port, boolean blocking, int timeout, String encoding) throws IOException { + super(ConnectionClass.Socket, modeString, AbstractOpenMode.Read, blocking, encoding); this.server = server; this.host = host; this.port = port; - this.blocking = blocking; this.timeout = timeout; openNonLazyConnection(); } @Override + @TruffleBoundary protected void createDelegateConnection() throws IOException { - DelegateRConnection delegate = server ? new RServerSocketConnection(this) : new RClientSocketConnection(this); + DelegateRConnection delegate; + if (server) { + delegate = new RServerSocketConnection(this); + } else { + if (isBlocking()) { + delegate = new RClientSocketConnection(this); + } else { + delegate = new RClientSocketNonBlockConnection(this); + } + } setDelegate(delegate); } @@ -75,22 +78,21 @@ public class SocketConnections { } } - private abstract static class RSocketReadWriteConnection extends DelegateReadWriteRConnection implements ReadWriteHelper { + private abstract static class RSocketReadWriteConnection extends DelegateReadWriteRConnection { private Socket socket; - private SocketChannel socketChannel; - protected InputStream inputStream; - protected OutputStream outputStream; + private SocketChannel channel; protected final RSocketConnection thisBase; protected RSocketReadWriteConnection(RSocketConnection base) { - super(base); + super(base, 0); this.thisBase = base; } - protected void openStreams(Socket socketArg) throws IOException { - this.socket = socketArg; - this.socketChannel = socket.getChannel(); - if (thisBase.blocking) { + protected void openStreams(SocketChannel socketArg) throws IOException { + channel = socketArg; + socket = socketArg.socket(); + if (thisBase.isBlocking()) { + channel.configureBlocking(true); // Java (int) timeouts do not meet the POSIX standard of 31 days long millisTimeout = ((long) thisBase.timeout) * 1000; if (millisTimeout > Integer.MAX_VALUE) { @@ -98,95 +100,69 @@ public class SocketConnections { } socket.setSoTimeout((int) millisTimeout); } else { - socketChannel.configureBlocking(false); + channel.configureBlocking(false); } - inputStream = socket.getInputStream(); - outputStream = socket.getOutputStream(); - } - - @Override - public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException { - return readLinesHelper(inputStream, n, warn, skipNul); - } - - @Override - public InputStream getInputStream() throws IOException { - return inputStream; - } - - @Override - public OutputStream getOutputStream() throws IOException { - return outputStream; - } - - @Override - public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException { - writeLinesHelper(outputStream, lines, sep); - } - - @Override - public void writeBin(ByteBuffer buffer) throws IOException { - writeBinHelper(buffer, outputStream); } @Override - public int readBin(ByteBuffer buffer) throws IOException { - return readBinHelper(buffer, inputStream); + public ByteChannel getChannel() { + return channel; } @Override - public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException { - writeCharHelper(outputStream, s, pad, eos); + public boolean isSeekable() { + return false; } + } - @Override - public void writeString(String s, boolean nl) throws IOException { - writeStringHelper(outputStream, s, nl); - } + private abstract static class RSocketReadWriteNonBlockConnection extends DelegateReadWriteRConnection { + private Socket socket; + private SocketChannel socketChannel; - @Override - public String readChar(int nchars, boolean useBytes) throws IOException { - return readCharHelper(nchars, inputStream, useBytes); + protected RSocketReadWriteNonBlockConnection(RSocketConnection base) { + super(base, 0); } - @Override - public byte[] readBinChars() throws IOException { - return readBinCharsHelper(inputStream); + protected void openStreams(Socket socketArg) throws IOException { + this.socket = socketArg; + this.socketChannel = socket.getChannel(); + socketChannel.configureBlocking(false); } @Override - public void flush() throws IOException { - outputStream.flush(); + public void close() throws IOException { + socketChannel.close(); + socket.close(); } @Override - public void closeAndDestroy() throws IOException { - base.closed = true; - close(); + public ByteChannel getChannel() { + return socketChannel; } @Override - public void close() throws IOException { - socket.close(); + public boolean isSeekable() { + return false; } } private static class RServerSocketConnection extends RSocketReadWriteConnection { - private final Socket connectionSocket; + private final SocketChannel connectionSocket; RServerSocketConnection(RSocketConnection base) throws IOException { super(base); InetSocketAddress addr = new InetSocketAddress(base.port); - ServerSocket serverSocket = new ServerSocket(); + ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); + // we expect only one connection per-server socket; furthermore, we need to accommodate // for multiple connections being established locally on the same server port; // consequently, we close the server socket at the end of the constructor and allow // address reuse to be able to open the next connection after the current one closes - serverSocket.setReuseAddress(true); - serverSocket.bind(addr); - connectionSocket = serverSocket.accept(); + serverSocketChannel.socket().setReuseAddress(true); + serverSocketChannel.socket().bind(addr); + connectionSocket = serverSocketChannel.accept(); openStreams(connectionSocket); - serverSocket.close(); + serverSocketChannel.close(); } @Override @@ -199,6 +175,15 @@ public class SocketConnections { private static class RClientSocketConnection extends RSocketReadWriteConnection { RClientSocketConnection(RSocketConnection base) throws IOException { + super(base); + SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(base.host, base.port)); + openStreams(socketChannel); + } + } + + private static class RClientSocketNonBlockConnection extends RSocketReadWriteNonBlockConnection { + + RClientSocketNonBlockConnection(RSocketConnection base) throws IOException { super(base); SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(base.host, base.port)); openStreams(socketChannel.socket()); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java index 22f8ca5d238f1834edc99797045c60ffdbac47c8..6150dc902b2cf11456b38457c64e489a62bf8f12 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.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 @@ -79,15 +79,15 @@ public class StdConnections { return RContext.getInstance().stateStdConnections; } - public static RConnection getStdin() { + public static BaseRConnection getStdin() { return getContextState().stdin; } - public static RConnection getStdout() { + public static BaseRConnection getStdout() { return getContextState().stdout; } - public static RConnection getStderr() { + public static BaseRConnection getStderr() { return getContextState().stderr; } @@ -161,7 +161,7 @@ public class StdConnections { } @Override - public RConnection forceOpen(String modeString) { + public BaseRConnection forceOpen(String modeString) { return this; } @@ -171,7 +171,7 @@ public class StdConnections { } @Override - public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { + public long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { throw RError.error(RError.SHOW_CALLER2, RError.Message.UNSEEKABLE_CONNECTION); } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java index 9434f758c41dffdab375149fbc3da7d08555a24d..b1e4629053bf14d0dc17abbeb8d257b162d0ffef 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java @@ -23,9 +23,9 @@ package com.oracle.truffle.r.runtime.conn; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; +import java.nio.channels.ByteChannel; import java.util.ArrayList; import com.oracle.truffle.r.runtime.RError; @@ -33,9 +33,6 @@ import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode; import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection; import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadRConnection; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateWriteRConnection; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @@ -45,7 +42,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment.PutException; public class TextConnections { public static class TextRConnection extends BaseRConnection { protected String description; - protected RAbstractStringVector object; + private final RAbstractStringVector object; protected REnvironment env; public TextRConnection(String description, RAbstractStringVector object, REnvironment env, String modeString) throws IOException { @@ -66,10 +63,14 @@ public class TextConnections { DelegateRConnection delegate = null; switch (getOpenMode().abstractOpenMode) { case Read: - delegate = new TextReadRConnection(this); + if (object != null) { + delegate = new TextReadRConnection(this, object); + } else { + throw RError.error(RError.SHOW_CALLER2, RError.Message.INVALID_ARGUMENT, "text"); + } break; case Write: - delegate = new TextWriteRConnection(this); + delegate = new TextWriteRConnection(this, object); break; default: throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + getOpenMode().modeString); @@ -77,24 +78,25 @@ public class TextConnections { setDelegate(delegate); } - public String[] getValue() { + public RAbstractStringVector getValue() { return ((GetConnectionValue) theConnection).getValue(); } } private interface GetConnectionValue { - String[] getValue(); + RAbstractStringVector getValue(); } private static class TextReadRConnection extends DelegateReadRConnection implements GetConnectionValue { private final String[] lines; private int index; - TextReadRConnection(TextRConnection base) { - super(base); + TextReadRConnection(TextRConnection base, RAbstractStringVector object) { + super(base, 0); + assert object != null; StringBuffer sb = new StringBuffer(); - for (int i = 0; i < base.object.getLength(); i++) { - sb.append(base.object.getDataAt(i)); + for (int i = 0; i < object.getLength(); i++) { + sb.append(object.getDataAt(i)); // vector elements are implicitly terminated with a newline sb.append('\n'); } @@ -102,7 +104,7 @@ public class TextConnections { } @Override - public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException { + public String[] readLines(int n, boolean warn, boolean skipNul) throws IOException { int nleft = lines.length - index; int nlines = nleft; if (n > 0) { @@ -115,44 +117,24 @@ public class TextConnections { return result; } - @SuppressWarnings("hiding") - @Override - public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException { - throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message); - } - - @Override - public InputStream getInputStream() throws IOException { - throw RInternalError.shouldNotReachHere(); - } - - @Override - public void closeAndDestroy() throws IOException { - base.closed = true; - } - - @Override - public void close() { - } - @Override - public int readBin(ByteBuffer buffer) throws IOException { - throw RError.nyi(null, "readBin on text connection"); + public void close() throws IOException { + // nothing to do } @Override - public byte[] readBinChars() throws IOException { - throw RError.nyi(null, "readBinChars on text connection"); + public boolean isSeekable() { + return false; } @Override - public String readChar(int nchars, boolean useBytes) throws IOException { - throw RError.nyi(null, "readChar on text connection"); + public ByteChannel getChannel() { + throw RInternalError.shouldNotReachHere(); } @Override - public String[] getValue() { - throw RError.nyi(null, "textConnectionValue"); + public RAbstractStringVector getValue() { + throw RError.error(RError.SHOW_CALLER2, RError.Message.NOT_AN_OUTPUT_TEXT_CONNECTION); } } @@ -160,31 +142,39 @@ public class TextConnections { private String incompleteLine; private RStringVector textVec; private String idName; + private RAbstractStringVector object; + + /** Indicates if the connection is anonymous, i.e., not input object has been provided. */ + private final boolean anonymous; private void initTextVec(RStringVector v, TextRConnection textBase) { - if (textBase.description.equals("NULL")) { - throw RError.nyi(null, "anonymous text output connection"); - } - idName = textBase.object.getDataAt(0); - try { - textVec = v; - textBase.env.put(idName, textVec); - } catch (PutException ex) { - throw RError.error(RError.SHOW_CALLER2, ex); + + if (anonymous) { + object = v; + } else { + idName = object.getDataAt(0); + try { + textVec = v; + textBase.env.put(idName, textVec); + } catch (PutException ex) { + throw RError.error(RError.SHOW_CALLER2, ex); + } + // lock the binding + textBase.env.lockBinding(idName); } - // lock the binding - textBase.env.lockBinding(idName); } - protected TextWriteRConnection(BaseRConnection base) { + protected TextWriteRConnection(BaseRConnection base, RAbstractStringVector object) { super(base); + this.object = object; + this.anonymous = object == null; TextRConnection textBase = (TextRConnection) base; initTextVec(RDataFactory.createStringVector(0), textBase); } @Override - public OutputStream getOutputStream() throws IOException { - return new ConnectionOutputStream(); + public ByteChannel getChannel() { + return ConnectionSupport.newChannel(new ConnectionOutputStream()); } @Override @@ -193,10 +183,17 @@ public class TextConnections { if (incompleteLine != null) { appendData(new String[]{incompleteLine}); incompleteLine = null; + base.setIncomplete(false); } base.closed = true; TextRConnection textBase = (TextRConnection) base; - textBase.env.unlockBinding(idName); + unlockBinding(textBase); + } + + private void unlockBinding(TextRConnection textBase) { + if (idName != null) { + textBase.env.unlockBinding(idName); + } } @Override @@ -210,8 +207,9 @@ public class TextConnections { ArrayList<String> appendedLines = new ArrayList<>(); while ((nlIndex = result.indexOf('\n', px)) >= 0) { if (incompleteLine != null) { - appendedLines.add(new StringBuffer(incompleteLine).append(result.substring(px, nlIndex)).toString()); + appendedLines.add(new StringBuilder(incompleteLine).append(result.substring(px, nlIndex)).toString()); incompleteLine = null; + base.setIncomplete(false); } else { appendedLines.add(result.substring(px, nlIndex)); } @@ -222,9 +220,11 @@ public class TextConnections { if (incompleteLine != null && !endOfLine) { // end of line not found - accumulate incomplete line incompleteLine = new StringBuffer(incompleteLine).append(result).toString(); + base.setIncomplete(true); } else if (px < result.length()) { // only reset incompleteLine if incompleteLine = result.substring(px); + base.setIncomplete(true); } if (appendedLines.size() > 0) { // update the vector data @@ -235,7 +235,7 @@ public class TextConnections { } void appendData(String[] appendedData) { - String[] existingData = textVec.getDataWithoutCopying(); + String[] existingData = textVec != null ? textVec.getDataWithoutCopying() : new String[0]; String[] updateData = appendedData; if (existingData.length > 0) { updateData = new String[existingData.length + appendedData.length]; @@ -243,11 +243,7 @@ public class TextConnections { System.arraycopy(appendedData, 0, updateData, existingData.length, appendedData.length); } TextRConnection textBase = (TextRConnection) base; - /* - * N.B. This assumes one thread per RContext else another thread could be calling - * lockBinding - */ - textBase.env.unlockBinding(idName); + unlockBinding(textBase); // TODO: is vector really complete? initTextVec(RDataFactory.createStringVector(updateData, RDataFactory.COMPLETE_VECTOR), textBase); } @@ -258,6 +254,7 @@ public class TextConnections { if (incompleteLine != null) { sb.append(incompleteLine); incompleteLine = null; + base.setIncomplete(false); } for (int i = 0; i < lines.getLength(); i++) { sb.append(lines.getDataAt(i)); @@ -277,17 +274,17 @@ public class TextConnections { @Override public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException { - throw RError.nyi(null, "writeChar on text connection"); + throw RError.error(RError.SHOW_CALLER2, RError.Message.NOT_ENABLED_FOR_THIS_CONN, "write"); } @Override public void writeBin(ByteBuffer buffer) throws IOException { - throw RError.nyi(null, "writeBin on text connection"); + throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_WRITE_BINARY_CONNECTION); } @Override - public String[] getValue() { - throw RError.nyi(null, "textConnectionValue"); + public RAbstractStringVector getValue() { + return object; } private class ConnectionOutputStream extends OutputStream { @@ -315,6 +312,16 @@ public class TextConnections { throw RInternalError.unimplemented(); } } + + @Override + protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException { + throw RError.error(RError.SHOW_CALLER, RError.Message.SEEK_NOT_RELEVANT_FOR_TEXT_CON); + } + + @Override + public boolean isSeekable() { + return false; + } } /** diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java index 7aad2be8e1da673e7e06da3e01258bc900eccacf..9bd5460030ab1a4fe14e3008922472f7c7ff978d 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java @@ -24,25 +24,21 @@ package com.oracle.truffle.r.runtime.conn; import java.io.BufferedInputStream; import java.io.IOException; -import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; -import java.nio.ByteBuffer; +import java.nio.channels.ByteChannel; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode; import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection; import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadRConnection; -import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ReadWriteHelper; public class URLConnections { public static class URLRConnection extends BaseRConnection { protected final String urlString; - public URLRConnection(String url, String modeString) throws IOException { - super(ConnectionClass.URL, modeString, AbstractOpenMode.Read); + public URLRConnection(String url, String modeString, String encoding) throws IOException { + super(ConnectionClass.URL, modeString, AbstractOpenMode.Read, encoding); this.urlString = url; } @@ -56,6 +52,7 @@ public class URLConnections { DelegateRConnection delegate = null; switch (getOpenMode().abstractOpenMode) { case Read: + case ReadBinary: delegate = new URLReadRConnection(this); break; default: @@ -65,50 +62,24 @@ public class URLConnections { } } - private static class URLReadRConnection extends DelegateReadRConnection implements ReadWriteHelper { + private static class URLReadRConnection extends DelegateReadRConnection { - private final BufferedInputStream inputStream; + private final ByteChannel rchannel; protected URLReadRConnection(URLRConnection base) throws MalformedURLException, IOException { super(base); URL url = new URL(base.urlString); - inputStream = new BufferedInputStream(url.openStream()); + rchannel = ConnectionSupport.newChannel(new BufferedInputStream(url.openStream())); } @Override - public int readBin(ByteBuffer buffer) throws IOException { - throw RError.nyi(null, "readBin on URL"); + public ByteChannel getChannel() { + return rchannel; } @Override - public byte[] readBinChars() throws IOException { - throw RError.nyi(null, "readBinChars on URL"); - } - - @Override - public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException { - return readLinesHelper(inputStream, n, warn, skipNul); - } - - @Override - public InputStream getInputStream() throws IOException { - return inputStream; - } - - @Override - public void closeAndDestroy() throws IOException { - base.closed = true; - close(); - } - - @Override - public void close() throws IOException { - inputStream.close(); - } - - @Override - public String readChar(int nchars, boolean useBytes) throws IOException { - return readCharHelper(nchars, inputStream, useBytes); + public boolean isSeekable() { + return false; } } } 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 f238108b70c6963f407b0fb1bcaaf09e6df6f49f..c30feafca92621778beef7300111b91d03aab0b7 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 @@ -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 @@ -67,10 +67,8 @@ public interface ConsoleHandler { void printError(String s); /** - * Read a line of input, newline included in result. Returns null if {@link #isInteractive() == - * false}. The rationale for including the readline is to ensure that the accumulated input, - * whether it be from a file or the console accurately reflects the the source. TODO worry about - * "\r\n"? + * 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(); 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 5e7770a8eaeb9140f95c3644caaea817a0a685f7..93ef3ba544ff1b8f3799caae8fc1aa1ebf65e5d7 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 @@ -23,13 +23,15 @@ package com.oracle.truffle.r.runtime.context; import java.util.TimeZone; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; -import com.oracle.truffle.api.interop.ForeignAccess; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.vm.PolyglotEngine; +import com.oracle.truffle.api.vm.PolyglotEngine.Builder; import com.oracle.truffle.r.runtime.RCmdOptions; import com.oracle.truffle.r.runtime.RCmdOptions.Client; +import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RStartParams; import com.oracle.truffle.r.runtime.context.RContext.ContextKind; @@ -39,10 +41,11 @@ import com.oracle.truffle.r.runtime.context.RContext.ContextKind; * Use {@link #createVM()} to apply this information to a newly-built {@link PolyglotEngine} * instance (it will be stored in the "fastrContextInfo" global symbol). */ -public final class ContextInfo implements TruffleObject { - public static final String GLOBAL_SYMBOL = "fastrContextInfo"; +public final class ContextInfo { + static final String CONFIG_KEY = "fastrContextInfo"; private static final AtomicInteger contextInfoIds = new AtomicInteger(); + private static final AtomicInteger multiSlotInds = new AtomicInteger(-1); private final RStartParams startParams; private final String[] env; @@ -56,26 +59,46 @@ public final class ContextInfo implements TruffleObject { private final RContext parent; private final ConsoleHandler consoleHandler; private final int id; + private final int multiSlotInd; private PolyglotEngine vm; + public Executor executor; - private ContextInfo(RStartParams startParams, String[] env, ContextKind kind, RContext parent, ConsoleHandler consoleHandler, TimeZone systemTimeZone, int id) { + private ContextInfo(RStartParams startParams, String[] env, ContextKind kind, RContext parent, ConsoleHandler consoleHandler, TimeZone systemTimeZone, int id, int multiSlotInd) { this.startParams = startParams; this.env = env; this.kind = kind; this.parent = parent; this.consoleHandler = consoleHandler; this.systemTimeZone = systemTimeZone; + this.multiSlotInd = multiSlotInd; this.id = id; } + /** + * Correctness of this method relies on the fact that parallel contexts are started only after + * all of them (and their info) is created (in FastRContext). + */ + public static int contextNum() { + return multiSlotInds.get() + 1; + } + + public static void resetMultiSlotIndexGenerator() { + multiSlotInds.set(0); // to account for primordial context + } + public PolyglotEngine createVM() { - PolyglotEngine newVM = PolyglotEngine.newBuilder().globalSymbol(GLOBAL_SYMBOL, this).build(); + Builder builder = PolyglotEngine.newBuilder(); + if (startParams.getInteractive()) { + this.executor = Executors.newSingleThreadExecutor(); + builder = builder.executor(executor); + } + PolyglotEngine newVM = builder.config("application/x-r", CONFIG_KEY, this).build(); this.vm = newVM; return newVM; } public PolyglotEngine createVM(PolyglotEngine.Builder builder) { - PolyglotEngine newVM = builder.globalSymbol(GLOBAL_SYMBOL, this).build(); + PolyglotEngine newVM = builder.config("application/x-r", CONFIG_KEY, this).build(); this.vm = newVM; return newVM; } @@ -93,7 +116,17 @@ public final class ContextInfo implements TruffleObject { */ public static ContextInfo create(RStartParams startParams, String[] env, ContextKind kind, RContext parent, ConsoleHandler consoleHandler, TimeZone systemTimeZone) { int id = contextInfoIds.incrementAndGet(); - return new ContextInfo(startParams, env, kind, parent, consoleHandler, systemTimeZone, id); + int multiSlotInd = multiSlotInds.get(); + if (kind == ContextKind.SHARE_ALL || kind == ContextKind.SHARE_NOTHING) { + multiSlotInd = multiSlotInds.incrementAndGet(); + } + // no increment for SHARE_PARENT_RW as it accesses the same data as its parent whose + // execution is suspended + if (kind == ContextKind.SHARE_PARENT_RO) { + throw RInternalError.shouldNotReachHere(); + } + assert kind != ContextKind.SHARE_PARENT_RW || (kind == ContextKind.SHARE_PARENT_RW && parent.getKind() == ContextKind.SHARE_NOTHING && parent.getMultiSlotInd() == 0); + return new ContextInfo(startParams, env, kind, parent, consoleHandler, systemTimeZone, id, kind == ContextKind.SHARE_PARENT_RW ? 0 : multiSlotInd); } public static ContextInfo create(RStartParams startParams, String[] env, ContextKind kind, RContext parent, ConsoleHandler consoleHandler) { @@ -115,10 +148,6 @@ public final class ContextInfo implements TruffleObject { return create(params, env, kind, parent, consoleHandler); } - public static ContextInfo getContextInfo(PolyglotEngine vm) { - return vm.findGlobalSymbol(ContextInfo.GLOBAL_SYMBOL).as(ContextInfo.class); - } - public RStartParams getStartParams() { return startParams; } @@ -147,12 +176,11 @@ public final class ContextInfo implements TruffleObject { return id; } - public PolyglotEngine getVM() { - return vm; + public int getMultiSlotInd() { + return multiSlotInd; } - @Override - public ForeignAccess getForeignAccess() { - throw new IllegalStateException("cannot access " + ContextInfo.class.getSimpleName() + " via Truffle"); + public PolyglotEngine getVM() { + return vm; } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java index ac6079435a58436bed6d286fe3e30f23d5048c51..6c7f7f692cc73dc2134594d4f5c71f4bc65dd99d 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java @@ -30,6 +30,7 @@ import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.vm.PolyglotEngine; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.data.RExpression; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RLanguage; @@ -39,6 +40,8 @@ import com.oracle.truffle.r.runtime.nodes.RNode; public interface Engine { + Source GET_CONTEXT = RSource.fromTextInternal("<<<get_context>>>", RSource.Internal.GET_CONTEXT); + class ParseException extends RuntimeException { private static final long serialVersionUID = 1L; 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 d9f04b454e74e5a5d15e8939021f8cd8316932ce..2a790546b7aeb33940bd9065e5bcea352b5f911e 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 @@ -32,17 +32,16 @@ import java.util.Map; import java.util.TimeZone; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Semaphore; import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.ExecutionContext; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.Instrumenter; -import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.vm.PolyglotEngine; @@ -61,7 +60,6 @@ import com.oracle.truffle.r.runtime.RProfile; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RRuntimeASTAccess; import com.oracle.truffle.r.runtime.RSerialize; -import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.RStartParams; import com.oracle.truffle.r.runtime.TempPathName; import com.oracle.truffle.r.runtime.Utils; @@ -74,7 +72,9 @@ import com.oracle.truffle.r.runtime.context.Engine.ParseException; 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.RNull; import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.RTruffleObject; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; @@ -102,7 +102,8 @@ import qir.ast.QIRNode; * * Contexts can be destroyed */ -public final class RContext extends ExecutionContext implements TruffleObject { +@SuppressWarnings("deprecation") +public final class RContext extends com.oracle.truffle.api.ExecutionContext implements RTruffleObject { private static int queryId = 0; public static final int INVALID_QUERY_ID = -1; // Static representation of queries. @@ -172,7 +173,12 @@ public final class RContext extends ExecutionContext implements TruffleObject { * shallow copy of the environments associated with the default packages of the parent * context at the time the context is created. */ - SHARE_PARENT_RO; + SHARE_PARENT_RO, + + /** + * Shares all environments on the search path. + */ + SHARE_ALL; public static final ContextKind[] VALUES = values(); } @@ -252,11 +258,10 @@ public final class RContext extends ExecutionContext implements TruffleObject { */ public static class EvalThread extends ContextThread { - private static final Source GET_CONTEXT = RSource.fromTextInternal("invisible(.fastr.context.get())", RSource.Internal.GET_CONTEXT); - private final Source source; private final ContextInfo info; private RList evalResult; + private Semaphore init = new Semaphore(0); public static final Map<Integer, Thread> threads = new ConcurrentHashMap<>(); @@ -269,12 +274,13 @@ public final class RContext extends ExecutionContext implements TruffleObject { @Override public void run() { - PolyglotEngine vm = info.createVM(); + PolyglotEngine vm = info.createVM(PolyglotEngine.newBuilder()); try { - setContext(vm.eval(GET_CONTEXT).as(RContext.class)); + setContext(vm.eval(Engine.GET_CONTEXT).as(RContext.class)); } catch (Throwable t) { throw new RInternalError(t, "error while initializing eval thread"); } + init.release(); try { evalResult = run(vm, info, source); } finally { @@ -283,6 +289,19 @@ public final class RContext extends ExecutionContext implements TruffleObject { } } + /* + * Parent context uses this method to wait for initialization of the child to complete to + * prevent potential updates to runtime's meta data from interfering with program's + * execution. + */ + public void waitForInit() { + try { + init.acquire(); + } catch (InterruptedException x) { + throw new RInternalError(x, "error waiting to initialize eval thread"); + } + } + /** * Convenience method for {@code .fastr.context.eval} in same thread. */ @@ -297,6 +316,9 @@ public final class RContext extends ExecutionContext implements TruffleObject { } catch (ExitException e) { // termination, treat this as "success" evalResult = RDataFactory.createList(new Object[]{e.getStatus()}); + } catch (RError e) { + // nothing to do + evalResult = RDataFactory.createList(new Object[]{RNull.instance}); } catch (Throwable t) { // some internal error RInternalError.reportErrorAndConsoleLog(t, info.getConsoleHandler(), info.getId()); @@ -424,6 +446,10 @@ public final class RContext extends ExecutionContext implements TruffleObject { private static final Assumption singleContextAssumption = Truffle.getRuntime().createAssumption("single RContext"); @CompilationFinal private static RContext singleContext; + // need an additional flag as we don't want multi-slot processing to start until context + // initialization is fully complete - singleContext flag is not good enough for that + private static final Assumption isSingleContextAssumption = Truffle.getRuntime().createAssumption("is single RContext"); + private final Env env; private final HashMap<String, TruffleObject> exportedSymbols = new HashMap<>(); private final boolean initial; @@ -461,7 +487,8 @@ public final class RContext extends ExecutionContext implements TruffleObject { public final WeakHashMap<Source, REnvironment> sourceRefEnvironments = new WeakHashMap<>(); private ContextState[] contextStates() { - return new ContextState[]{stateREnvVars, stateRProfile, stateROptions, stateREnvironment, stateRErrorHandling, stateRConnection, stateStdConnections, stateRNG, stateRFFI, stateRSerialize, + return new ContextState[]{stateREnvVars, stateRProfile, stateTempPath, stateROptions, stateREnvironment, stateRErrorHandling, stateRConnection, stateStdConnections, stateRNG, stateRFFI, + stateRSerialize, stateLazyDBCache, stateInstrumentation, stateDLL}; } @@ -481,7 +508,7 @@ public final class RContext extends ExecutionContext implements TruffleObject { * @param isInitial {@code true} if this is the initial (primordial) context. */ private RContext(Env env, Instrumenter instrumenter, boolean isInitial) { - ContextInfo initialInfo = (ContextInfo) env.importSymbol(ContextInfo.GLOBAL_SYMBOL); + Object initialInfo = env.getConfig().get(ContextInfo.CONFIG_KEY); if (initialInfo == null) { /* * This implies that FastR is being invoked initially from another Truffle language and @@ -491,7 +518,7 @@ public final class RContext extends ExecutionContext implements TruffleObject { this.info = ContextInfo.create(new RStartParams(RCmdOptions.parseArguments(Client.R, new String[]{"--no-restore"}, false), false), null, ContextKind.SHARE_NOTHING, null, new DefaultConsoleHandler(env.in(), env.out())); } else { - this.info = initialInfo; + this.info = (ContextInfo) initialInfo; } this.initial = isInitial; @@ -501,7 +528,7 @@ public final class RContext extends ExecutionContext implements TruffleObject { this.stateROptions = ROptions.ContextStateImpl.newContextState(stateREnvVars); this.stateRProfile = RProfile.newContextState(stateREnvVars); this.stateStdConnections = StdConnections.ContextStateImpl.newContextState(); - this.stateREnvironment = REnvironment.ContextStateImpl.newContextState(); + this.stateREnvironment = REnvironment.ContextStateImpl.newContextState(this); this.stateRErrorHandling = RErrorHandling.ContextStateImpl.newContextState(); this.stateRConnection = ConnectionSupport.ContextStateImpl.newContextState(); this.stateRNG = RRNG.ContextStateImpl.newContextState(); @@ -672,6 +699,14 @@ public final class RContext extends ExecutionContext implements TruffleObject { return info.getKind(); } + public int getId() { + return info.getId(); + } + + public int getMultiSlotInd() { + return info.getMultiSlotInd(); + } + @TruffleBoundary public static RContext getThreadLocalInstance() { return threadLocalContext.get(); @@ -690,6 +725,14 @@ public final class RContext extends ExecutionContext implements TruffleObject { return result; } + public static boolean isSingle() { + return isSingleContextAssumption.isValid(); + } + + public static void markNonSingle() { + isSingleContextAssumption.invalidate(); + } + public static RContext getInstance() { RContext context = singleContext; if (singleContextAssumption.isValid() && context != null) { @@ -746,6 +789,7 @@ public final class RContext extends ExecutionContext implements TruffleObject { s4ExtendsTable.put(key, value); } + @TruffleBoundary public PrimitiveMethodsInfo getPrimitiveMethodsInfo() { if (primitiveMethodsInfo == null) { // shared contexts do not run concurrently with their parent and re-use primitive @@ -815,6 +859,19 @@ public final class RContext extends ExecutionContext implements TruffleObject { return info.getEnv(); } + public boolean hasExecutor() { + return info.executor != null; + } + + /** + * Allows another thread to schedule some code to be run in this context's thread. The action + * can be scheduled only if PolyglotEngine was created with an Executor. + */ + public void schedule(Runnable action) { + assert hasExecutor() : "Cannot run RContext#schedule() when there is no executor."; + info.executor.execute(action); + } + @Override public String toString() { return "context: " + info.getId(); @@ -870,11 +927,6 @@ public final class RContext extends ExecutionContext implements TruffleObject { nameSpaceName = name; } - @Override - public ForeignAccess getForeignAccess() { - throw new IllegalStateException("cannot access " + RContext.class.getSimpleName() + " via Truffle"); - } - public interface RCloseable extends Closeable { @Override void close(); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/MemoryCopyTracer.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/MemoryCopyTracer.java index ecba6aeb9d75ef8362287e2d6d3da379319ec767..7316b4b323d488808dbbb0f1a5bdda7a7114a2b4 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/MemoryCopyTracer.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/MemoryCopyTracer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -27,7 +27,9 @@ import java.util.Deque; import java.util.concurrent.ConcurrentLinkedDeque; import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; /** @@ -71,10 +73,16 @@ public final class MemoryCopyTracer { * no-op. */ public static void reportCopying(RAbstractVector source, RAbstractVector dest) { + assert RContext.getInstance() != null : "valid context needed whenever copying could be reported"; if (!noMemoryCopyTracingAssumption.isValid() && enabled) { - for (Listener listener : listeners) { - listener.reportCopying(source, dest); - } + notifyListeners(source, dest); + } + } + + @TruffleBoundary + private static void notifyListeners(RAbstractVector source, RAbstractVector dest) { + for (Listener listener : listeners) { + listener.reportCopying(source, dest); } } 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 18a0cb472db916172c7386ab5e62fb9334a0552f..dc5b6529b927da17c556388083bd25322e654b8d 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,13 +22,21 @@ */ package com.oracle.truffle.r.runtime.data; +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 { static { - final String prop = System.getProperty("fastr.objectsize.factory.class", "com.oracle.truffle.r.runtime.data.AgentObjectSizeFactory"); + String prop = System.getProperty("fastr.objectsize.factory.class"); + if (prop == null) { + if (FastRConfig.ManagedMode) { + prop = SimpleObjectSizeFactory.class.getName(); + } else { + prop = AgentObjectSizeFactory.class.getName(); + } + } try { theInstance = (ObjectSizeFactory) Class.forName(prop).newInstance(); } catch (Exception ex) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java index 661b24b02db8e595bb4454767d088448bb1aa9e9..dd34471c65db4e2fb93c3b6e32f8f398d5eb8793 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java @@ -25,7 +25,6 @@ package com.oracle.truffle.r.runtime.data; import java.util.Iterator; import com.oracle.truffle.api.CompilerAsserts; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.env.REnvironment; @@ -53,33 +52,6 @@ public interface RAttributable extends RTypedValue { */ DynamicObject getAttributes(); - /** - * Returns the value of the {@code class} attribute or empty {@link RStringVector} if class - * attribute is not set. - */ - @TruffleBoundary - default RStringVector getClassHierarchy() { - Object v = getAttr(RRuntime.CLASS_ATTR_KEY); - RStringVector result = v instanceof RStringVector ? (RStringVector) v : getImplicitClass(); - return result != null ? result : RDataFactory.createEmptyStringVector(); - } - - /** - * Returns {@code true} if the {@code class} attribute is set to {@link RStringVector} whose - * first element equals to the given className. - */ - default boolean hasClass(String className) { - RStringVector v = getClassHierarchy(); - for (int i = 0; i < v.getLength(); ++i) { - if (v.getDataAt(i).equals(className)) { - return true; - } - } - return false; - } - - RStringVector getImplicitClass(); - /** * Get the value of an attribute. Returns {@code null} if not set. */ @@ -152,7 +124,6 @@ public interface RAttributable extends RTypedValue { /** * Returns {@code true} if and only if the value has a {@code class} attribute added explicitly. - * When {@code true}, it is possible to call {@link RAttributable#getClassHierarchy()}. */ default boolean isObject() { return getClassAttr() != null ? true : false; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.java index 0c8cd8620dc67331bc2c41985324344297cb3f4b..b02f1044bcd7681d57b25df27a118b65aba29116 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.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 @@ -49,7 +49,4 @@ public abstract class RAttributeStorage extends RBaseObject implements RAttribut public final void initAttributes(DynamicObject newAttributes) { this.attributes = newAttributes; } - - @Override - public abstract RStringVector getImplicitClass(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java index dcbcfd1fb1c6b4c20b3bb0d661edd14bb3d9445f..e928ee140a045b2c9bc89268f8e28fe1964c11b2 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.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 @@ -28,7 +28,7 @@ import com.oracle.truffle.api.CompilerDirectives.ValueType; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.closures.RClosures; +import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -57,9 +57,9 @@ public final class RComplex extends RScalarVector implements RAbstractComplexVec case Complex: return this; case Character: - return RClosures.createComplexToStringVector(this); + return RString.valueOf(RContext.getRRuntimeASTAccess().encodeComplex(this)); case List: - return RClosures.createAbstractVectorToListVector(this); + return RScalarList.valueOf(this); default: return null; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java index 585753ac6fe8858cc44a94668e42df1ff2c63b24..5e7b39ec4557d4a3b697acabcdb3d287f08a7a4e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.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 @@ -35,8 +35,6 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; public final class RComplexVector extends RVector<double[]> implements RAbstractComplexVector { - public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Complex.getClazz()); - private final double[] data; RComplexVector(double[] data, boolean complete, int[] dims, RStringVector names) { @@ -71,9 +69,9 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract case Complex: return this; case Character: - return RClosures.createComplexToStringVector(this); + return RClosures.createToStringVector(this); case List: - return RClosures.createAbstractVectorToListVector(this); + return RClosures.createToListVector(this); default: return null; } @@ -106,7 +104,7 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract } @Override - protected boolean internalVerify() { + public boolean verify() { if (isComplete()) { for (double d : data) { if (d == RRuntime.DOUBLE_NA) { @@ -172,9 +170,9 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract } @Override - protected RComplexVector internalCopyResized(int size, boolean fillNA) { + protected RComplexVector internalCopyResized(int size, boolean fillNA, int[] dimensions) { boolean isComplete = isComplete() && ((data.length >= size) || !fillNA); - return RDataFactory.createComplexVector(copyResizedData(size, fillNA), isComplete); + return RDataFactory.createComplexVector(copyResizedData(size, fillNA), isComplete, dimensions); } @Override @@ -195,9 +193,4 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract data[toIndex2] = value.getRealPart(); data[toIndex2 + 1] = value.getImaginaryPart(); } - - @Override - public RStringVector getImplicitClass() { - return getClassHierarchyHelper(implicitClassHeader); - } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java index db2e0bbd3fef317ff7794efdc6eb9b36947646ac..2192e8f0598c9b472336e793a2cefe92a5593ef8 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java @@ -31,6 +31,7 @@ import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; +import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.utilities.CyclicAssumption; import com.oracle.truffle.r.runtime.FastROptions; @@ -375,13 +376,33 @@ public final class RDataFactory { } public static RList createList(int n) { - return createList(new Object[n], null, null); + return createList(createRNullArray(n), null, null); + } + + public static RList createList(int size, RStringVector names) { + if (names == null) { + return createList(size); + } + assert size == names.getLength(); + return createList(createRNullArray(names.getLength()), null, names); } public static RList createList(Object[] data, int[] newDimensions, RStringVector names) { return traceDataCreated(new RList(data, newDimensions, names)); } + public static RExpression createExpression(int size) { + return createExpression(createRNullArray(size)); + } + + public static RExpression createExpression(int size, RStringVector names) { + if (names == null) { + return createExpression(size); + } + assert size == names.getLength(); + return createExpression(createRNullArray(size), names); + } + public static RExpression createExpression(Object[] data, int[] newDimensions) { return traceDataCreated(new RExpression(data, newDimensions, null)); } @@ -437,7 +458,7 @@ public final class RDataFactory { if (FastROptions.noEagerEval()) { throw RInternalError.shouldNotReachHere(); } - return traceDataCreated(new RPromise.PromisedPromise(exprClosure, eagerValue, notChangedNonLocally, targetFrame, feedback)); + return traceDataCreated(new RPromise.EagerPromise(PromiseState.Promised, exprClosure, eagerValue, notChangedNonLocally, targetFrame, feedback, -1)); } public static Object createLangPairList(int size) { @@ -479,6 +500,11 @@ public final class RDataFactory { return traceDataCreated(new REnvironment.NewEnv(RRuntime.createNonFunctionFrame("<internal-env-" + environmentCount.incrementAndGet() + ">"), REnvironment.UNNAMED)); } + @TruffleBoundary + public static REnvironment.NewEnv createNewEnv(FrameDescriptor desc, String name) { + return traceDataCreated(new REnvironment.NewEnv(RRuntime.createNewFrame(desc), name)); + } + @TruffleBoundary public static REnvironment.NewEnv createNewEnv(String name) { return traceDataCreated(new REnvironment.NewEnv(RRuntime.createNonFunctionFrame("<new-env-" + environmentCount.incrementAndGet() + ">"), name)); @@ -558,4 +584,10 @@ public final class RDataFactory { public static void addListener(Listener listener) { listeners.addLast(listener); } + + private static Object[] createRNullArray(int size) { + Object[] data = new Object[size]; + Arrays.fill(data, RNull.instance); + return data; + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java index e729e7a1e9eb8d61534c670cbab467b1df9f198f..1a034e6bf2826b734c754652aeed229adb94dc5d 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.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 @@ -27,7 +27,7 @@ import com.oracle.truffle.api.CompilerDirectives.ValueType; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.closures.RClosures; +import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -63,9 +63,9 @@ public final class RDouble extends RScalarVector implements RAbstractDoubleVecto // From 3.3.0 on, only "true" NA values are converted to complex NA return isNAProfile.profile(RRuntime.isNA(value)) ? RComplex.createNA() : RComplex.valueOf(value, 0.0); case Character: - return RClosures.createDoubleToStringVector(this); + return RString.valueOf(RContext.getRRuntimeASTAccess().encodeDouble(value)); case List: - return RClosures.createAbstractVectorToListVector(this); + return RScalarList.valueOf(this); default: return null; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java index eaf92cff20f646ea6e4d988beded67914d17ea40..2cf039de0743c86ed84b3f189fd24d5a9522dc78 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java @@ -73,16 +73,16 @@ public final class RDoubleSequence extends RSequence implements RAbstractDoubleV public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { // TODO might be possible to implement some of these without closures switch (type) { + case Integer: + return RClosures.createToIntVector(this); case Double: return this; - case Integer: - return RClosures.createDoubleToIntVector(this); case Complex: - return RClosures.createDoubleToComplexVector(this); + return RClosures.createToComplexVector(this); case Character: - return RClosures.createDoubleToStringVector(this); + return RClosures.createToStringVector(this); case List: - return RClosures.createAbstractVectorToListVector(this); + return RClosures.createToListVector(this); default: return null; } @@ -90,7 +90,7 @@ public final class RDoubleSequence extends RSequence implements RAbstractDoubleV private RDoubleVector populateVectorData(double[] result) { double current = start; - for (int i = 0; i < getLength(); i++) { + for (int i = 0; i < result.length && i < getLength(); i++) { result[i] = current; current += stride; } @@ -108,16 +108,20 @@ public final class RDoubleSequence extends RSequence implements RAbstractDoubleV } @Override - public RStringVector getImplicitClass() { - return RDoubleVector.implicitClassHeader; + public RDoubleVector copyResized(int size, boolean fillNA) { + double[] data = new double[size]; + populateVectorData(data); + RDoubleVector.resizeData(data, data, getLength(), fillNA); + return RDataFactory.createDoubleVector(data, !(fillNA && size > getLength())); } @Override - public RDoubleVector copyResized(int size, boolean fillNA) { + public RVector<?> copyResizedWithDimensions(int[] newDimensions, boolean fillNA) { + int size = newDimensions[0] * newDimensions[1]; double[] data = new double[size]; populateVectorData(data); RDoubleVector.resizeData(data, data, getLength(), fillNA); - return RDataFactory.createDoubleVector(data, !(fillNA && size > getLength())); + return RDataFactory.createDoubleVector(data, !(fillNA && size > getLength()), newDimensions); } @Override diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java index be3aaec3c9c8f8b69eb6a5403c0050cbbb345ed9..e4eace8649f0ecd70396b1798ab2db31860fe6db 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.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 @@ -35,8 +35,6 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; public final class RDoubleVector extends RVector<double[]> implements RAbstractDoubleVector { - public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Double.getClazz()); - private final double[] data; RDoubleVector(double[] data, boolean complete, int[] dims, RStringVector names) { @@ -52,16 +50,16 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD @Override public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { switch (type) { + case Integer: + return RClosures.createToIntVector(this); case Double: return this; - case Integer: - return RClosures.createDoubleToIntVector(this); case Complex: - return RClosures.createDoubleToComplexVector(this); + return RClosures.createToComplexVector(this); case Character: - return RClosures.createDoubleToStringVector(this); + return RClosures.createToStringVector(this); case List: - return RClosures.createAbstractVectorToListVector(this); + return RClosures.createToListVector(this); default: return null; } @@ -113,7 +111,7 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD } @Override - protected boolean internalVerify() { + public boolean verify() { if (isComplete()) { for (double d : data) { if (d == RRuntime.DOUBLE_NA) { @@ -185,9 +183,9 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD } @Override - protected RDoubleVector internalCopyResized(int size, boolean fillNA) { + protected RDoubleVector internalCopyResized(int size, boolean fillNA, int[] dimensions) { boolean isComplete = isComplete() && ((data.length >= size) || !fillNA); - return RDataFactory.createDoubleVector(copyResizedData(size, fillNA), isComplete); + return RDataFactory.createDoubleVector(copyResizedData(size, fillNA), isComplete, dimensions); } @Override @@ -210,9 +208,4 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD public Object getDataAtAsObject(int index) { return getDataAt(index); } - - @Override - public RStringVector getImplicitClass() { - return getClassHierarchyHelper(implicitClassHeader); - } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java index d4fed1887aef2d38c1428fbd94bdd07d022ec582..4c064cf3cb5555c458fb56e9edbfaac35888062e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java @@ -28,9 +28,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -public class RExpression extends RListBase implements RAbstractVector { - - private static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Expression.getClazz()); +public final class RExpression extends RListBase implements RAbstractVector { RExpression(Object[] data, int[] dims, RStringVector names) { super(data, dims, names); @@ -70,7 +68,7 @@ public class RExpression extends RListBase implements RAbstractVector { @Override public RExpression createEmptySameType(int newLength, boolean newIsComplete) { - return RDataFactory.createExpression(new Object[newLength]); + return RDataFactory.createExpression(newLength); } @Override @@ -79,12 +77,8 @@ public class RExpression extends RListBase implements RAbstractVector { } @Override - protected RExpression internalCopyResized(int size, boolean fillNA) { - return RDataFactory.createExpression(copyResizedData(size, fillNA)); + protected RExpression internalCopyResized(int size, boolean fillNA, int[] dimensions) { + return RDataFactory.createExpression(copyResizedData(size, fillNA), dimensions); } - @Override - public RStringVector getImplicitClass() { - return getClassHierarchyHelper(implicitClassHeader); - } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.java index eddf195c7b72b93340f887cd8441f302b5ddebf0..639450e7440cf0abbd65a88beda2d3f760389140 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.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 @@ -92,10 +92,4 @@ public class RExternalPtr extends RAttributeStorage implements RTypedValue { return RType.ExternalPtr; } - private static final RStringVector implicitClass = RDataFactory.createStringVector(RType.ExternalPtr.getName()); - - @Override - public final RStringVector getImplicitClass() { - return implicitClass; - } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java index 52144392a9bb6fb2fc4027c8193eeadbc5c906d7..6aa8daa0c098e2863619e687adda0594003a5387 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.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 @@ -68,6 +68,9 @@ public final class RFunction extends RSharingAttributeStorage implements RTypedV @Override public RType getRType() { + // Note: GnuR distinguishes "builtins" and "specials" (BUILTINSXP vs SPECIALSXP). The later + // has non-evaluated args. FastR and GnuR built-ins differ in whether they have evaluated + // args, so we cannot correcly choose RType.Special here. return isBuiltin() ? RType.Builtin : RType.Closure; } @@ -99,13 +102,6 @@ public final class RFunction extends RSharingAttributeStorage implements RTypedV return enclosingFrame; } - private static final RStringVector implicitClass = RDataFactory.createStringVectorFromScalar(RType.Function.getName()); - - @Override - public RStringVector getImplicitClass() { - return implicitClass; - } - @Override public String toString() { return target.toString(); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java index ed1daeb266c538e015a5cad9b09785e962c9ae09..a5aea4b6f6ca4347adebbbf7248a22d8d0c3dc83 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java @@ -55,11 +55,11 @@ public final class RIntSequence extends RSequence implements RAbstractIntVector case Double: return RDataFactory.createDoubleSequence(getStart(), getStride(), getLength()); case Complex: - return RClosures.createIntToComplexVector(this); + return RClosures.createToComplexVector(this); case Character: - return RClosures.createIntToStringVector(this); + return RClosures.createToStringVector(this); case List: - return RClosures.createAbstractVectorToListVector(this); + return RClosures.createToListVector(this); default: return null; } @@ -85,7 +85,7 @@ public final class RIntSequence extends RSequence implements RAbstractIntVector private RIntVector populateVectorData(int[] result) { int current = start; - for (int i = 0; i < getLength(); i++) { + for (int i = 0; i < result.length && i < getLength(); i++) { result[i] = current; current += stride; } @@ -113,16 +113,20 @@ public final class RIntSequence extends RSequence implements RAbstractIntVector } @Override - public RStringVector getImplicitClass() { - return RIntVector.implicitClassHeader; + public RIntVector copyResized(int size, boolean fillNA) { + int[] data = new int[size]; + populateVectorData(data); + RIntVector.resizeData(data, data, getLength(), fillNA); + return RDataFactory.createIntVector(data, !(fillNA && size > getLength())); } @Override - public RIntVector copyResized(int size, boolean fillNA) { + public RVector<?> copyResizedWithDimensions(int[] newDimensions, boolean fillNA) { + int size = newDimensions[0] * newDimensions[1]; int[] data = new int[size]; populateVectorData(data); RIntVector.resizeData(data, data, getLength(), fillNA); - return RDataFactory.createIntVector(data, !(fillNA && size > getLength())); + return RDataFactory.createIntVector(data, !(fillNA && size > getLength()), newDimensions); } @Override diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java index c1a53a35f6249ef756e29261fc3d67d3332fd8d7..8fa15af2a36250faf14c7d2bd464ece0d2be187c 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.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 @@ -35,8 +35,6 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; public final class RIntVector extends RVector<int[]> implements RAbstractIntVector { - public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Integer.getClazz()); - private final int[] data; RIntVector(int[] data, boolean complete, int[] dims, RStringVector names) { @@ -52,16 +50,16 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect @Override public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { switch (type) { - case Double: - return RClosures.createIntToDoubleVector(this); case Integer: return this; + case Double: + return RClosures.createToDoubleVector(this); case Complex: - return RClosures.createIntToComplexVector(this); + return RClosures.createToComplexVector(this); case Character: - return RClosures.createIntToStringVector(this); + return RClosures.createToStringVector(this); case List: - return RClosures.createAbstractVectorToListVector(this); + return RClosures.createToListVector(this); default: return null; } @@ -118,7 +116,7 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect } @Override - protected boolean internalVerify() { + public boolean verify() { if (isComplete()) { for (int x : data) { if (x == RRuntime.INT_NA) { @@ -184,9 +182,9 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect } @Override - protected RIntVector internalCopyResized(int size, boolean fillNA) { + protected RIntVector internalCopyResized(int size, boolean fillNA, int[] dimensions) { boolean isComplete = isComplete() && ((data.length >= size) || !fillNA); - return RDataFactory.createIntVector(copyResizedData(size, fillNA), isComplete); + return RDataFactory.createIntVector(copyResizedData(size, fillNA), isComplete, dimensions); } @Override @@ -210,11 +208,6 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect return getDataAt(index); } - @Override - public RStringVector getImplicitClass() { - return getClassHierarchyHelper(implicitClassHeader); - } - @Override public void setElement(int i, Object value) { data[i] = (int) value; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.java index 33ba1ebd83bac82664770babb137ec2908cf5148..3a618e1ff53c4c1f638f1543806c1e276cc4829d 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.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 @@ -26,7 +26,6 @@ import com.oracle.truffle.api.CompilerDirectives.ValueType; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.closures.RClosures; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -72,9 +71,9 @@ public final class RInteger extends RScalarVector implements RAbstractIntVector case Complex: return isNAProfile.profile(isNA()) ? RComplex.createNA() : RComplex.valueOf(value, 0.0); case Character: - return RClosures.createIntToStringVector(this); + return RString.valueOf(RRuntime.intToString(value)); case List: - return RClosures.createAbstractVectorToListVector(this); + return RScalarList.valueOf(this); default: return null; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteropScalar.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteropScalar.java new file mode 100644 index 0000000000000000000000000000000000000000..ff5c016239dd80019ff542bd6af86ce6d0930b0b --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteropScalar.java @@ -0,0 +1,230 @@ +/* + * 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 + * 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.runtime.data; + +import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.api.CompilerDirectives.ValueType; +import com.oracle.truffle.r.runtime.RType; + +@ValueType +public abstract class RInteropScalar extends RScalar { + + public abstract Object getRValue(); + + public abstract Class<?> getJavaType(); + + @ValueType + public static final class RInteropByte extends RInteropScalar { + + private final byte value; + + private RInteropByte(byte value) { + this.value = value; + } + + public static RInteropByte valueOf(byte value) { + return new RInteropByte(value); + } + + public byte getValue() { + return value; + } + + @Override + public Object getRValue() { + return ((Byte) value).intValue(); + } + + @Override + public RType getRType() { + return RType.RInteropByte; + } + + @Override + public String toString() { + CompilerAsserts.neverPartOfCompilation(); + return Byte.toString(value); + } + + @Override + public Class<?> getJavaType() { + return Byte.TYPE; + } + } + + @ValueType + public static final class RInteropChar extends RInteropScalar { + + private final char value; + + private RInteropChar(char value) { + this.value = value; + } + + public static RInteropChar valueOf(char value) { + return new RInteropChar(value); + } + + public char getValue() { + return value; + } + + @Override + public Object getRValue() { + return Character.toString(value); + } + + @Override + public RType getRType() { + return RType.RInteropChar; + } + + @Override + public String toString() { + CompilerAsserts.neverPartOfCompilation(); + return Character.toString(value); + } + + @Override + public Class<?> getJavaType() { + return Character.TYPE; + } + } + + @ValueType + public static final class RInteropFloat extends RInteropScalar { + + private final float value; + + private RInteropFloat(float value) { + this.value = value; + } + + public static RInteropFloat valueOf(float value) { + return new RInteropFloat(value); + } + + public float getValue() { + return value; + } + + @Override + public Object getRValue() { + return ((Float) value).doubleValue(); + } + + @Override + public RType getRType() { + return RType.RInteropFloat; + } + + @Override + public String toString() { + CompilerAsserts.neverPartOfCompilation(); + return Float.toString(value); + } + + @Override + public Class<?> getJavaType() { + return Float.TYPE; + } + } + + @ValueType + public static final class RInteropLong extends RInteropScalar { + + private final long value; + + private RInteropLong(long value) { + this.value = value; + } + + public static RInteropLong valueOf(long value) { + return new RInteropLong(value); + } + + public long getValue() { + return value; + } + + @Override + public Object getRValue() { + return ((Long) value).doubleValue(); + } + + @Override + public RType getRType() { + return RType.RInteropLong; + } + + @Override + public String toString() { + CompilerAsserts.neverPartOfCompilation(); + return Long.toString(value); + } + + @Override + public Class<?> getJavaType() { + return Long.TYPE; + } + } + + @ValueType + public static final class RInteropShort extends RInteropScalar { + + private final short value; + + private RInteropShort(short value) { + this.value = value; + } + + public static RInteropShort valueOf(short value) { + return new RInteropShort(value); + } + + public short getValue() { + return value; + } + + @Override + public Object getRValue() { + return ((Short) value).intValue(); + } + + @Override + public RType getRType() { + return RType.RInteropShort; + } + + @Override + public String toString() { + CompilerAsserts.neverPartOfCompilation(); + return Short.toString(value); + } + + @Override + public Class<?> getJavaType() { + return Short.TYPE; + } + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java index 9166d94a99f94b95d74faaad099b036a21d300d1..ed06179415b6664a02f7c636e3f3e317cea37ea4 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java @@ -160,12 +160,7 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont } @Override - public Class<?> getElementClass() { - return RLanguage.class; - } - - @Override - public RShareable materializeToShareable() { + public RLanguage materialize() { // TODO is copy necessary? return copy(); } @@ -230,11 +225,6 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont attr.setAttr(RRuntime.ROWNAMES_ATTR_KEY, rowNames); } - @Override - public RStringVector getImplicitClass() { - return RDataFactory.createStringVector(RRuntime.CLASS_LANGUAGE); - } - @Override public RLanguage copy() { RLanguage l = new RLanguage(getRep(), this.length); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java index f9082b3bb9646e1cb727e4929f8055883f2df52e..e0dea79dbdf32083f1d006f49363d8983aa5af67 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java @@ -25,13 +25,10 @@ package com.oracle.truffle.r.runtime.data; import java.util.Arrays; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; public final class RList extends RListBase implements RAbstractListVector { - public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.List.getClazz()); - public String elementNamePrefix; RList(Object[] data, int[] dims, RStringVector names) { @@ -70,7 +67,7 @@ public final class RList extends RListBase implements RAbstractListVector { @Override public RList createEmptySameType(int newLength, boolean newIsComplete) { - return RDataFactory.createList(new Object[newLength]); + return RDataFactory.createList(newLength); } @Override @@ -79,12 +76,8 @@ public final class RList extends RListBase implements RAbstractListVector { } @Override - protected RList internalCopyResized(int size, boolean fillNA) { - return RDataFactory.createList(copyResizedData(size, fillNA)); + protected RList internalCopyResized(int size, boolean fillNA, int[] dimensions) { + return RDataFactory.createList(copyResizedData(size, fillNA), dimensions); } - @Override - public RStringVector getImplicitClass() { - return getClassHierarchyHelper(implicitClassHeader); - } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java index 537d54d73051c4026054cb467d2661f4b271bf06..abd4bf2d470f48fa9cc444720952e6ec17ef19c6 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.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 @@ -24,7 +24,6 @@ package com.oracle.truffle.r.runtime.data; import java.util.Arrays; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.data.model.RAbstractListBaseVector; @@ -80,6 +79,7 @@ public abstract class RListBase extends RVector<Object[]> implements RAbstractLi @Override public void setDataAt(Object store, int index, Object valueArg) { + assert valueArg != null : "lists must not contain nulls"; Object value = valueArg; assert store == data; ((Object[]) store)[index] = value; @@ -91,7 +91,12 @@ public abstract class RListBase extends RVector<Object[]> implements RAbstractLi } @Override - protected final boolean internalVerify() { + public final boolean verify() { + for (Object item : data) { + if (item == null) { + return false; + } + } return true; } @@ -123,6 +128,7 @@ public abstract class RListBase extends RVector<Object[]> implements RAbstractLi public final RListBase updateDataAt(int i, Object right, @SuppressWarnings("unused") NACheck rightNACheck) { assert !this.isShared() : "data in shared list must not be updated, make a copy"; + assert right != null : "lists must not contain nulls"; data[i] = right; return this; } @@ -139,30 +145,6 @@ public abstract class RListBase extends RVector<Object[]> implements RAbstractLi data[toIndex] = other.getDataAtAsObject(fromIndex); } - @Override - public final Class<?> getElementClass() { - return Object.class; - } - - @TruffleBoundary - public final Object getNameAt(int index) { - RStringVector names = getNamesFromAttrs(); - if (names != null && names != null) { - String name = names.getDataAt(index); - if (name == RRuntime.STRING_NA) { - return "$" + RRuntime.NA_HEADER; - } else if (name.equals(RRuntime.NAMES_ATTR_EMPTY_VALUE)) { - return "[[" + Integer.toString(index + 1) + "]]"; - } else if (name.matches("^[a-zA-Z.][a-zA-Z0-9_.]*$")) { - return "$" + name; - } else { - return "$`" + name + "`"; - } - } else { - return "[[" + Integer.toString(index + 1) + "]]"; - } - } - /** * Note: elements inside lists may be in inconsistent state reference counting wise. You may * need to put them into consistent state depending on what you use them for, consult the diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java index 44e432804a569f815eeb52fe6b9533d3f79c97a4..b0a64de5abacb4d56adc4cb4dd8111e27687eb0e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.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 @@ -26,7 +26,6 @@ import com.oracle.truffle.api.CompilerDirectives.ValueType; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.closures.RClosures; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -67,9 +66,9 @@ public final class RLogical extends RScalarVector implements RAbstractLogicalVec case Complex: return isNAProfile.profile(isNA()) ? RComplex.createNA() : RComplex.valueOf(value, 0.0); case Character: - return RClosures.createLogicalToStringVector(this); + return RString.valueOf(RRuntime.logicalToString(value)); case List: - return RClosures.createAbstractVectorToListVector(this); + return RScalarList.valueOf(this); default: return null; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java index f35b7730df0d7c173f5d7e682d4576b6213135bf..ed3fc3d9597bbe51ceb02ee05f9d04aca3cccf33 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.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 @@ -35,8 +35,6 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; public final class RLogicalVector extends RVector<byte[]> implements RAbstractLogicalVector { - public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Logical.getClazz()); - private final byte[] data; RLogicalVector(byte[] data, boolean complete, int[] dims, RStringVector names) { @@ -54,16 +52,16 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo switch (type) { case Logical: return this; - case Double: - return RClosures.createLogicalToDoubleVector(this); case Integer: - return RClosures.createLogicalToIntVector(this); + return RClosures.createToIntVector(this); + case Double: + return RClosures.createToDoubleVector(this); case Complex: - return RClosures.createLogicalToComplexVector(this); + return RClosures.createToComplexVector(this); case Character: - return RClosures.createLogicalToStringVector(this); + return RClosures.createToStringVector(this); case List: - return RClosures.createAbstractVectorToListVector(this); + return RClosures.createToListVector(this); default: return null; } @@ -115,7 +113,7 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo } @Override - protected boolean internalVerify() { + public boolean verify() { if (isComplete()) { for (byte b : data) { if (b == RRuntime.LOGICAL_NA) { @@ -164,9 +162,9 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo } @Override - protected RLogicalVector internalCopyResized(int size, boolean fillNA) { + protected RLogicalVector internalCopyResized(int size, boolean fillNA, int[] dimensions) { boolean isComplete = isComplete() && ((data.length >= size) || !fillNA); - return RDataFactory.createLogicalVector(copyResizedData(size, fillNA), isComplete); + return RDataFactory.createLogicalVector(copyResizedData(size, fillNA), isComplete, dimensions); } @Override @@ -209,8 +207,4 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo return getDataAt(index); } - @Override - public RStringVector getImplicitClass() { - return getClassHierarchyHelper(implicitClassHeader); - } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RNull.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RNull.java index 744db91b5755f260fb4f62ad944a529c1e1e6902..c006c4d9ef30270fe766818eaf4989c129c69919 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RNull.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RNull.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 @@ -27,8 +27,6 @@ import com.oracle.truffle.r.runtime.RType; public final class RNull extends RScalar { - public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Null.getName()); - public static final RNull instance = new RNull(); private RNull() { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java index 145bda60e2272170cf53f3645c88387a1c29fd92..18c853f56ae813bcfb2153c521b1464929092fea 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java @@ -211,6 +211,17 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra return type; } + /** + * Appends given value as the last element of the pairlist. + */ + public void appendToEnd(RPairList value) { + RPairList last = null; + for (RPairList item : this) { + last = item; + } + last.setCdr(value); + } + @Override public boolean isComplete() { // TODO: is it important to get more precise information here? @@ -251,12 +262,7 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra } @Override - public Class<?> getElementClass() { - return null; - } - - @Override - public RShareable copy() { + public RSharingAttributeStorage copy() { RPairList result = new RPairList(); Object original = this; while (!isNull(original)) { @@ -280,9 +286,8 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra } @Override - public RShareable materializeToShareable() { - RInternalError.shouldNotReachHere(); - return null; + public RPairList materialize() { + return this; } @Override @@ -346,11 +351,6 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra throw RInternalError.unimplemented(); } - @Override - public RStringVector getImplicitClass() { - return RDataFactory.createStringVector(RType.PairList.getName()); - } - @Override public boolean isObject() { return false; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java index 3e4b0807dd59742ab524841ad766da70654a62a2..cdb65dbbb957235d9dfec9dc55625d5da653694b 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.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,8 +39,10 @@ import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant; import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; /** @@ -275,7 +277,7 @@ public class RPromise implements RTypedValue { * originally read from has not been altered in the mean time. If this cannot be guaranteed for * any reason, a Promise gets {@link #deoptimize()} (which includes {@link #materialize()}ion). */ - public static class EagerPromiseBase extends RPromise { + public static final class EagerPromise extends RPromise { private final Object eagerValue; private final Assumption notChangedNonLocally; @@ -289,7 +291,7 @@ public class RPromise implements RTypedValue { */ private boolean deoptimized = false; - EagerPromiseBase(PromiseState state, Closure closure, Object eagerValue, Assumption notChangedNonLocally, RCaller targetFrame, EagerFeedback feedback, int wrapIndex) { + EagerPromise(PromiseState state, Closure closure, Object eagerValue, Assumption notChangedNonLocally, RCaller targetFrame, EagerFeedback feedback, int wrapIndex) { super(state, (MaterializedFrame) null, closure); assert state != PromiseState.Explicit; this.eagerValue = eagerValue; @@ -346,26 +348,6 @@ public class RPromise implements RTypedValue { } } - /** - * This is a "proper" eager promise. - */ - public static final class EagerPromise extends EagerPromiseBase { - EagerPromise(PromiseState state, Closure closure, Object eagerValue, Assumption notChangedNonLocally, RCaller targetFrame, EagerFeedback feedback, int wrapIndex) { - super(state, closure, eagerValue, notChangedNonLocally, targetFrame, feedback, wrapIndex); - } - } - - /** - * It's a variant of an eager promise used to store another promise, distinguished mostly for - * accounting purposes. - */ - public static final class PromisedPromise extends EagerPromiseBase { - - PromisedPromise(Closure closure, Object eagerValue, Assumption notChangedNonLocally, RCaller targetFrame, EagerFeedback feedback) { - super(PromiseState.Promised, closure, eagerValue, notChangedNonLocally, targetFrame, feedback, -1); - } - } - /** * Used to allow feedback on {@link EagerPromise} evaluation. */ @@ -445,14 +427,27 @@ public class RPromise implements RTypedValue { private final RBaseNode expr; private final String symbol; + private final String stringConstant; private Closure(RBaseNode expr) { this.expr = expr; if (expr.asRSyntaxNode() instanceof RSyntaxLookup) { - this.symbol = ((RSyntaxLookup) expr.asRSyntaxNode()).getIdentifier(); + this.symbol = ((RSyntaxLookup) expr.asRSyntaxNode()).getIdentifier().intern(); } else { this.symbol = null; } + if (expr.asRSyntaxNode() instanceof RSyntaxConstant) { + Object constant = ((RSyntaxConstant) expr.asRSyntaxNode()).getValue(); + if (constant instanceof String) { + this.stringConstant = (String) constant; + } else if (constant instanceof RAbstractStringVector && ((RAbstractStringVector) constant).getLength() == 1) { + this.stringConstant = ((RAbstractStringVector) constant).getDataAt(0); + } else { + this.stringConstant = null; + } + } else { + this.stringConstant = null; + } } public static Closure create(RBaseNode expr) { @@ -491,6 +486,10 @@ public class RPromise implements RTypedValue { public String asSymbol() { return symbol; } + + public String asStringConstant() { + return stringConstant; + } } @Override diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java index 138c53d05712073d0e6941b8a566ef0c2db40e20..0c55726d53efdf18f95c15a6b20d7f417302a930 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.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 @@ -24,9 +24,9 @@ package com.oracle.truffle.r.runtime.data; import com.oracle.truffle.api.CompilerDirectives.ValueType; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.Utils; -import com.oracle.truffle.r.runtime.data.closures.RClosures; import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -56,7 +56,7 @@ public final class RRaw extends RScalarVector implements RAbstractRawVector { case Complex: return RComplex.valueOf(value, 0.0); case Character: - return RClosures.createRawToStringVector(this); + return RString.valueOf(RRuntime.rawToString(this)); default: return null; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java index 6fdbf806bf2d4e258c6eeb0d133dd3dc0ae0be9c..85c9947b3c887b134cd18a779929d3fa630e9e36 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.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 @@ -35,8 +35,6 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; public final class RRawVector extends RVector<byte[]> implements RAbstractRawVector { - public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Raw.getClazz()); - private final byte[] data; RRawVector(byte[] data, int[] dims, RStringVector names) { @@ -55,13 +53,13 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec case Raw: return this; case Integer: - return RClosures.createRawToIntVector(this); + return RClosures.createToIntVector(this); case Double: - return RClosures.createRawToDoubleVector(this); + return RClosures.createToDoubleVector(this); case Complex: - return RClosures.createRawToComplexVector(this); + return RClosures.createToComplexVector(this); case Character: - return RClosures.createRawToStringVector(this); + return RClosures.createToStringVector(this); default: return null; } @@ -105,7 +103,7 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec } @Override - protected boolean internalVerify() { + public boolean verify() { return true; } @@ -161,8 +159,8 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec } @Override - protected RRawVector internalCopyResized(int size, boolean fillNA) { - return RDataFactory.createRawVector(copyResizedData(size, fillNA)); + protected RRawVector internalCopyResized(int size, boolean fillNA, int[] dimensions) { + return RDataFactory.createRawVector(copyResizedData(size, fillNA), dimensions); } @Override @@ -181,9 +179,4 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec public Object getDataAtAsObject(int index) { return getDataAt(index); } - - @Override - public RStringVector getImplicitClass() { - return getClassHierarchyHelper(implicitClassHeader); - } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RS4Object.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RS4Object.java index 9fca4608967bff8adc1c397ffa1acbe3a8fe51e9..1f706daf9e4bb2025111fa73255ad0b4fde3e4c7 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RS4Object.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RS4Object.java @@ -30,17 +30,10 @@ import com.oracle.truffle.r.runtime.RType; */ public final class RS4Object extends RSharingAttributeStorage { - private static final RStringVector implicitClass = RDataFactory.createStringVectorFromScalar("S4"); - public RS4Object() { setS4(); } - @Override - public RStringVector getImplicitClass() { - return implicitClass; - } - @Override public RType getRType() { return RType.S4Object; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RAbstactVectorToListClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarList.java similarity index 51% rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RAbstactVectorToListClosure.java rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarList.java index 4d076c044ef7f3d59ad3b6f6ffc59ef547bcac07..48e050c17b68e3dafd469bbb20dea8e73cc5e2be 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RAbstactVectorToListClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarList.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 @@ -20,51 +20,71 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.data.closures; +package com.oracle.truffle.r.runtime.data; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RVector; +import com.oracle.truffle.api.CompilerDirectives.ValueType; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -/** - * In converting complex numbers to integers, this closure discards the imaginary parts. - */ -final class RAbstactVectorToListClosure extends RToVectorClosure implements RAbstractListVector { +@ValueType +public final class RScalarList extends RScalarVector implements RAbstractListVector { + + private final Object value; - RAbstactVectorToListClosure(RAbstractVector vector) { - super(vector); + private RScalarList(Object value) { + this.value = value; } - @Override - public Object getDataAtAsObject(int index) { - return vector.getDataAtAsObject(index); + public static RScalarList valueOf(Object value) { + return new RScalarList(value); } @Override public Object getDataAt(int index) { - return vector.getDataAtAsObject(index); + assert index == 0; + return value; + } + + public Object getValue() { + return value; } @Override - public RList materialize() { - int length = getLength(); - Object[] result = new Object[length]; - for (int i = 0; i < length; i++) { - Object data = getDataAtAsObject(i); - result[i] = data; + public RType getRType() { + return RType.List; + } + + @Override + public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { + switch (type) { + case List: + return this; + default: + return null; } - return RDataFactory.createList(result); } @Override - public RAbstractVector copyWithNewDimensions(int[] newDimensions) { - return materialize().copyWithNewDimensions(newDimensions); + public String toString() { + return value.toString(); + } + + @Override + public RList materialize() { + RList result = RDataFactory.createList(new Object[]{value}); + MemoryCopyTracer.reportCopying(this, result); + return result; + } + + @Override + public Object getDataAtAsObject(int index) { + return getDataAt(index); } @Override - public RVector<?> createEmptySameType(int newLength, boolean newIsComplete) { - return RDataFactory.createList(new Object[newLength]); + public boolean isNA() { + return false; } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java index 94892c2553c495a34f81ea4a6cbeffb7705f0dcc..80f1da3147b21cc03ee8a51ea175c0307f59413c 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java @@ -31,16 +31,6 @@ public abstract class RScalarVector extends RScalar implements RAbstractVector { public abstract boolean isNA(); - @Override - public final RStringVector getClassHierarchy() { - return RDataFactory.createStringVector(getRType().getName()); - } - - @Override - public final RStringVector getImplicitClass() { - return RDataFactory.createStringVector(getRType().getName()); - } - @Override public final RScalarVector copy() { return this; @@ -87,11 +77,6 @@ public abstract class RScalarVector extends RScalar implements RAbstractVector { return materialize().getNonShared(); } - @Override - public RShareable materializeToShareable() { - return materialize().materializeToShareable(); - } - @Override public RStringVector getNames() { return null; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java index 2167dd74eb15107a32ab61a9e1e7f7d9a614538d..d9aa895489f362128e582c828f9161b20a408d2e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java @@ -172,30 +172,11 @@ public abstract class RSequence implements RAbstractVector { return false; } - @Override - public final RStringVector getClassHierarchy() { - return getImplicitClass(); - } - @Override public final RTypedValue getNonShared() { return materialize().getNonShared(); } - @Override - public final RShareable materializeToShareable() { - return this.materialize(); - } - - @Override - public final RVector<?> copyResizedWithDimensions(int[] newDimensions, boolean fillNA) { - // TODO support for higher dimensions - assert newDimensions.length == 2; - RVector<?> result = copyResized(newDimensions[0] * newDimensions[1], fillNA); - result.setDimensions(newDimensions); - return result; - } - @Override public int getTypedValueInfo() { return 0; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSharingAttributeStorage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSharingAttributeStorage.java index a685b13e48aaaef62c457462dbf5731b96aa370a..7a0797ee3628eea4feaf37dfc53823fac55c1e28 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSharingAttributeStorage.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSharingAttributeStorage.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 @@ -76,4 +76,15 @@ public abstract class RSharingAttributeStorage extends RAttributeStorage impleme } return this; } + + @Override + public abstract RSharingAttributeStorage copy(); + + /** + * Verifies that the given object either is and instance of RShareable and + * RSharingAttributeStorage or an instance of neither of them. + */ + public static void verify(Object value) { + assert (value instanceof RShareable) == (value instanceof RSharingAttributeStorage) : "unexpected RShareable that is not RSharingAttributeStorage: " + value; + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.java index af3281e0c19f749edcdbd5f3ab44ed4562315ce6..98b4b5653f6f931907b8fb5b23b83b26ad582e82 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.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 @@ -27,7 +27,6 @@ import com.oracle.truffle.api.CompilerDirectives.ValueType; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.closures.RClosures; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -54,7 +53,7 @@ public final class RString extends RScalarVector implements RAbstractStringVecto case Character: return this; case List: - return RClosures.createAbstractVectorToListVector(this); + return RScalarList.valueOf(this); default: return null; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java index b4110bd81af1e69378fa0eff2b77030a7ef682ff..32e0a2c866408d7b66b444fa494d1a841ee705aa 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.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 @@ -36,8 +36,6 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck; public final class RStringVector extends RVector<String[]> implements RAbstractStringVector { - public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Character.getClazz()); - private final String[] data; RStringVector(String[] data, boolean complete, int[] dims, RStringVector names) { @@ -56,7 +54,7 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS case Character: return this; case List: - return RClosures.createAbstractVectorToListVector(this); + return RClosures.createToListVector(this); default: return null; } @@ -111,7 +109,7 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS } @Override - protected boolean internalVerify() { + public boolean verify() { if (isComplete()) { for (String b : data) { if (b == RRuntime.STRING_NA) { @@ -166,9 +164,9 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS } @Override - protected RStringVector internalCopyResized(int size, boolean fillNA) { + protected RStringVector internalCopyResized(int size, boolean fillNA, int[] dimensions) { boolean isComplete = isComplete() && ((data.length >= size) || !fillNA); - return RDataFactory.createStringVector(copyResizedData(size, fillNA ? RRuntime.STRING_NA : null), isComplete); + return RDataFactory.createStringVector(copyResizedData(size, fillNA ? RRuntime.STRING_NA : null), isComplete, dimensions); } public RStringVector resizeWithEmpty(int size) { @@ -201,11 +199,6 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS return getDataAt(index); } - @Override - public RStringVector getImplicitClass() { - return getClassHierarchyHelper(implicitClassHeader); - } - @Override public void setElement(int i, Object value) { data[i] = (String) value; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java index 378b61fb82aea3f35d8d2bab2ccfbb0e6aa6baf5..ad8f31449e1039194392bc5b23d1f525e9bc34cc 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.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 @@ -23,7 +23,6 @@ package com.oracle.truffle.r.runtime.data; import com.oracle.truffle.api.CompilerDirectives.ValueType; -import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; /** @@ -55,13 +54,6 @@ public final class RSymbol extends RAttributeStorage { return name; } - private static final RStringVector implicitClass = RDataFactory.createStringVectorFromScalar(RRuntime.CLASS_SYMBOL); - - @Override - public RStringVector getImplicitClass() { - return implicitClass; - } - public boolean isMissing() { return name.isEmpty(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypedValue.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypedValue.java index d66dda64a73c8daae1ed80004def6eefe04b157d..153949e45e9d8ed54ec4614f4b6e9e51ffed9155 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypedValue.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypedValue.java @@ -6,7 +6,7 @@ * Copyright (c) 1995, 1996, 1997 Robert Gentleman and Ross Ihaka * Copyright (c) 1995-2014, The R Core Team * Copyright (c) 2002-2008, The R Foundation - * Copyright (c) 2015, 2016, Oracle and/or its affiliates + * Copyright (c) 2015, 2017, Oracle and/or its affiliates * * All rights reserved. */ diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java index 6b473ad2b615ed131f5eacece8e8fced1c4b0e5f..f11da3d123650f52a9ed9c974c93284153ae10de 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.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 @@ -26,15 +26,17 @@ import com.oracle.truffle.api.dsl.ImplicitCast; import com.oracle.truffle.api.dsl.TypeCast; import com.oracle.truffle.api.dsl.TypeCheck; import com.oracle.truffle.api.dsl.TypeSystem; -import com.oracle.truffle.api.dsl.internal.DSLOptions; -import com.oracle.truffle.api.dsl.internal.DSLOptions.DSLGenerator; -import com.oracle.truffle.api.frame.FrameSlot; -import com.oracle.truffle.api.frame.MaterializedFrame; -import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropByte; +import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropChar; +import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropFloat; +import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropLong; +import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropShort; +import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; 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.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @@ -49,12 +51,30 @@ import com.oracle.truffle.r.runtime.nodes.RNode; * * @see RNode */ -@TypeSystem({boolean.class, byte.class, int.class, double.class, RRaw.class, RComplex.class, String.class, RIntSequence.class, RDoubleSequence.class, RIntVector.class, RDoubleVector.class, - RRawVector.class, RComplexVector.class, RStringVector.class, RLogicalVector.class, RFunction.class, RNull.class, RMissing.class, REmpty.class, REnvironment.class, RExpression.class, - MaterializedFrame.class, FrameSlot.class, RAbstractIntVector.class, RAbstractDoubleVector.class, RAbstractLogicalVector.class, RAbstractComplexVector.class, - RAbstractStringVector.class, RAbstractRawVector.class, RList.class, RAbstractVector.class, RSymbol.class, RPromise.class, RLanguage.class, - RPairList.class, RExternalPtr.class, RS4Object.class, RAbstractContainer.class, RAttributable.class, RArgsValuesAndNames.class, RTypedValue.class, RType.class, Object[].class}) -@DSLOptions(defaultGenerator = DSLGenerator.DEFAULT) +@TypeSystem({ + byte.class, RAbstractLogicalVector.class, RInteropByte.class, + RInteropChar.class, + RInteropFloat.class, + RInteropLong.class, + RInteropShort.class, + int.class, RAbstractIntVector.class, + double.class, RAbstractDoubleVector.class, + String.class, RAbstractStringVector.class, + RRaw.class, RAbstractRawVector.class, + RComplex.class, RAbstractComplexVector.class, + RAbstractListVector.class, + RNull.class, + RExpression.class, + RPromise.class, + RMissing.class, + RPairList.class, + RSymbol.class, + RLanguage.class, + RFunction.class, + REnvironment.class, + RAbstractContainer.class, + RArgsValuesAndNames.class +}) public class RTypes { @TypeCheck(RNull.class) @@ -109,56 +129,6 @@ public class RTypes { return RDataFactory.createStringVectorFromScalar(value); } - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RIntVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RDoubleVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RLogicalVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RComplexVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RRawVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RStringVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RIntSequence vector) { - return vector; - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RDoubleSequence vector) { - return vector; - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RList vector) { - return vector; - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RAbstractVector vector) { - return vector; - } - @ImplicitCast public static RAbstractVector toAbstractVector(int value) { return RDataFactory.createIntVectorFromScalar(value); @@ -189,119 +159,64 @@ public class RTypes { return RDataFactory.createStringVectorFromScalar(value); } - @ImplicitCast - public static RAbstractVector toAbstractVector(RIntVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(RDoubleVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(RLogicalVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(RComplexVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(RRawVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(RStringVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(RIntSequence vector) { - return vector; - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(RDoubleSequence vector) { - return vector; - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(RList vector) { - return vector; - } - @ImplicitCast public static RAbstractIntVector toAbstractIntVector(int value) { return RDataFactory.createIntVectorFromScalar(value); } - @ImplicitCast - public static RAbstractIntVector toAbstractIntVector(RIntSequence vector) { - return vector; - } - - @ImplicitCast - public static RAbstractIntVector toAbstractIntVector(RIntVector vector) { - return vector; - } - @ImplicitCast public static RAbstractDoubleVector toAbstractDoubleVector(double value) { return RDataFactory.createDoubleVectorFromScalar(value); } @ImplicitCast - public static RAbstractDoubleVector toAbstractDoubleVector(RDoubleSequence vector) { - return vector; + public static RAbstractComplexVector toAbstractComplexVector(RComplex vector) { + return RDataFactory.createComplexVectorFromScalar(vector); } @ImplicitCast - public static RAbstractDoubleVector toAbstractDoubleVector(RDoubleVector vector) { - return vector; + public static RAbstractLogicalVector toAbstractLogicalVector(byte vector) { + return RDataFactory.createLogicalVectorFromScalar(vector); } @ImplicitCast - public static RAbstractComplexVector toAbstractComplexVector(RComplexVector vector) { - return vector; + public static RAbstractRawVector toAbstractRawVector(RRaw vector) { + return RDataFactory.createRawVectorFromScalar(vector); } @ImplicitCast - public static RAbstractComplexVector toAbstractComplexVector(RComplex vector) { - return RDataFactory.createComplexVectorFromScalar(vector); + public static RAbstractStringVector toAbstractStringVector(String vector) { + return RDataFactory.createStringVectorFromScalar(vector); } @ImplicitCast - public static RAbstractLogicalVector toAbstractLogicalVector(byte vector) { - return RDataFactory.createLogicalVectorFromScalar(vector); + public static RAbstractAtomicVector toAbstractAtomicVector(int value) { + return RDataFactory.createIntVectorFromScalar(value); } @ImplicitCast - public static RAbstractLogicalVector toAbstractLogicalVector(RLogicalVector vector) { - return vector; + public static RAbstractAtomicVector toAbstractAtomicVector(double value) { + return RDataFactory.createDoubleVectorFromScalar(value); } @ImplicitCast - public static RAbstractRawVector toAbstractRawVector(RRaw vector) { - return RDataFactory.createRawVectorFromScalar(vector); + public static RAbstractAtomicVector toAbstractAtomicVector(RRaw value) { + return RDataFactory.createRawVectorFromScalar(value); } @ImplicitCast - public static RAbstractRawVector toAbstractRawVector(RRawVector vector) { - return vector; + public static RAbstractAtomicVector toAbstractAtomicVector(byte value) { + return RDataFactory.createLogicalVectorFromScalar(value); } @ImplicitCast - public static RAbstractStringVector toAbstractStringVector(String vector) { - return RDataFactory.createStringVectorFromScalar(vector); + public static RAbstractAtomicVector toAbstractAtomicVector(RComplex value) { + return RDataFactory.createComplexVectorFromScalar(value); } @ImplicitCast - public static RAbstractStringVector toAbstractStringVector(RStringVector vector) { - return vector; + public static RAbstractAtomicVector toAbstractAtomicVector(String value) { + return RDataFactory.createStringVectorFromScalar(value); } @ImplicitCast diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypesFlatLayout.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypesFlatLayout.java deleted file mode 100644 index b0c6f4bbb0b8657cf152bd2be46dd695523c0903..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypesFlatLayout.java +++ /dev/null @@ -1,377 +0,0 @@ -/* - * 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 - * 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.runtime.data; - -import com.oracle.truffle.api.dsl.ImplicitCast; -import com.oracle.truffle.api.dsl.TypeCast; -import com.oracle.truffle.api.dsl.TypeCheck; -import com.oracle.truffle.api.dsl.TypeSystem; -import com.oracle.truffle.api.dsl.internal.DSLOptions; -import com.oracle.truffle.api.dsl.internal.DSLOptions.DSLGenerator; -import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; -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.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -import com.oracle.truffle.r.runtime.nodes.RNode; - -/** - * Whenever you add a type {@code T} to the list below, make sure a corresponding {@code executeT()} - * method is added to {@link RNode}, a {@code typeof} method is added to {@code TypeoNode} and a - * {@code print} method added to {code PrettyPrinterNode}. - * - * @see RNode - */ -@TypeSystem({byte.class, int.class, double.class}) -@DSLOptions(defaultGenerator = DSLGenerator.FLAT) -public class RTypesFlatLayout { - - @TypeCheck(RNull.class) - public static boolean isRNull(Object value) { - return value == RNull.instance; - } - - @TypeCast(RNull.class) - @SuppressWarnings("unused") - public static RNull asRNull(Object value) { - return RNull.instance; - } - - @TypeCheck(RMissing.class) - public static boolean isRMissing(Object value) { - return value == RMissing.instance; - } - - @TypeCast(RMissing.class) - @SuppressWarnings("unused") - public static RMissing asRMissing(Object value) { - return RMissing.instance; - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(int value) { - return RDataFactory.createIntVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(double value) { - return RDataFactory.createDoubleVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RRaw value) { - return RDataFactory.createRawVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(byte value) { - return RDataFactory.createLogicalVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RComplex value) { - return RDataFactory.createComplexVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(String value) { - return RDataFactory.createStringVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RIntVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RDoubleVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RLogicalVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RComplexVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RRawVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RStringVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RIntSequence vector) { - return vector; - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RDoubleSequence vector) { - return vector; - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RList vector) { - return vector; - } - - @ImplicitCast - public static RAbstractContainer toAbstractContainer(RAbstractVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(int value) { - return RDataFactory.createIntVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(double value) { - return RDataFactory.createDoubleVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(RRaw value) { - return RDataFactory.createRawVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(byte value) { - return RDataFactory.createLogicalVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(RComplex value) { - return RDataFactory.createComplexVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(String value) { - return RDataFactory.createStringVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(RIntVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(RDoubleVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(RLogicalVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(RComplexVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(RRawVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(RStringVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(RIntSequence vector) { - return vector; - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(RDoubleSequence vector) { - return vector; - } - - @ImplicitCast - public static RAbstractVector toAbstractVector(RList vector) { - return vector; - } - - @ImplicitCast - public static RAbstractIntVector toAbstractIntVector(int value) { - return RDataFactory.createIntVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractIntVector toAbstractIntVector(RIntSequence vector) { - return vector; - } - - @ImplicitCast - public static RAbstractIntVector toAbstractIntVector(RIntVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractDoubleVector toAbstractDoubleVector(double value) { - return RDataFactory.createDoubleVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractDoubleVector toAbstractDoubleVector(RDoubleSequence vector) { - return vector; - } - - @ImplicitCast - public static RAbstractDoubleVector toAbstractDoubleVector(RDoubleVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractComplexVector toAbstractComplexVector(RComplexVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractComplexVector toAbstractComplexVector(RComplex vector) { - return RDataFactory.createComplexVectorFromScalar(vector); - } - - @ImplicitCast - public static RAbstractLogicalVector toAbstractLogicalVector(byte vector) { - return RDataFactory.createLogicalVectorFromScalar(vector); - } - - @ImplicitCast - public static RAbstractLogicalVector toAbstractLogicalVector(RLogicalVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractRawVector toAbstractRawVector(RRaw vector) { - return RDataFactory.createRawVectorFromScalar(vector); - } - - @ImplicitCast - public static RAbstractRawVector toAbstractRawVector(RRawVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractStringVector toAbstractStringVector(String vector) { - return RDataFactory.createStringVectorFromScalar(vector); - } - - @ImplicitCast - public static RAbstractStringVector toAbstractStringVector(RStringVector vector) { - return vector; - } - - @ImplicitCast - public static RMissing toRMissing(@SuppressWarnings("unused") REmpty empty) { - return RMissing.instance; - } - - // RAbstractAtomicVector - - @ImplicitCast - public static RAbstractAtomicVector toAbstractAtomicVector(int value) { - return RDataFactory.createIntVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractAtomicVector toAbstractAtomicVector(double value) { - return RDataFactory.createDoubleVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractAtomicVector toAbstractAtomicVector(RRaw value) { - return RDataFactory.createRawVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractAtomicVector toAbstractAtomicVector(byte value) { - return RDataFactory.createLogicalVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractAtomicVector toAbstractAtomicVector(RComplex value) { - return RDataFactory.createComplexVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractAtomicVector toAbstractAtomicVector(String value) { - return RDataFactory.createStringVectorFromScalar(value); - } - - @ImplicitCast - public static RAbstractAtomicVector toAbstractAtomicVector(RIntVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractAtomicVector toAbstractAtomicVector(RDoubleVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractAtomicVector toAbstractAtomicVector(RLogicalVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractAtomicVector toAbstractAtomicVector(RComplexVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractAtomicVector toAbstractAtomicVector(RRawVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractAtomicVector toAbstractAtomicVector(RStringVector vector) { - return vector; - } - - @ImplicitCast - public static RAbstractAtomicVector toAbstractAtomicVector(RIntSequence vector) { - return vector; - } - - @ImplicitCast - public static RAbstractVector toAbstractAtomicVector(RDoubleSequence vector) { - return vector; - } - -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java index e5e7d62026859376ee80d452416cc5d7a00c15be..5af392c0858ff416f7d37a96a11f27436e593744 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java @@ -96,23 +96,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement } } - private RList getDimNamesFromAttrs() { - if (attributes == null) { - return null; - } else { - return (RList) attributes.get(RRuntime.DIMNAMES_ATTR_KEY); - } - } - - private Object getRowNamesFromAttrs() { - if (attributes == null) { - return null; - } else { - return attributes.get(RRuntime.ROWNAMES_ATTR_KEY); - } - } - - protected final RStringVector getNamesFromAttrs() { + private RStringVector getNamesFromAttrs() { if (attributes == null) { return null; } else { @@ -151,10 +135,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement return isTemporary() ? getDataWithoutCopying() : getDataCopy(); } - public final int[] getInternalDimensions() { - return getDimensionsFromAttrs(); - } - @Override public final void setComplete(boolean complete) { this.complete = complete; @@ -203,37 +183,8 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement return -1; } - /** - * Find the first element in the names list that {@code name} is a prefix of, and return its - * index. If there are no names, or none is found, or there are multiple inexact matches, return - * -1. - */ - @TruffleBoundary - public final int getElementIndexByNameInexact(String name) { - if (getNames() == null) { - return -1; - } - boolean oneMatch = false; - int match = -1; - RStringVector names = getNamesFromAttrs(); - for (int i = 0; i < names.getLength(); i++) { - if (names.getDataAt(i).startsWith(name)) { - if (oneMatch) { - return -1; - } else { - match = i; - oneMatch = true; - } - } - } - return match; - } - /** * Guarded method that checks whether {@code attributes} is initialized. - * - * @param attribute - * @param value */ private void putAttribute(String attribute, Object value) { initAttributes().define(attribute, value); @@ -292,20 +243,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement } } - /** - * Sets names attribute without doing any error checking - to be used sparingly. - * - * @param newNames - */ - public final void setNamesNoCheck(RStringVector newNames) { - if (newNames == null) { - removeAttributeMapping(RRuntime.NAMES_ATTR_KEY); - } else { - putAttribute(RRuntime.NAMES_ATTR_KEY, newNames); - } - assert newNames != this; - } - @Override public final void setNames(RStringVector newNames) { // TODO pass invoking Node @@ -338,7 +275,11 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement @Override public final RList getDimNames() { - return getDimNamesFromAttrs(); + if (attributes == null) { + return null; + } else { + return (RList) attributes.get(RRuntime.DIMNAMES_ATTR_KEY); + } } /** @@ -367,25 +308,27 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement } else if (newDimNames != null) { int[] dimensions = getDimensionsFromAttrs(); if (dimensions == null) { - throw RError.error(invokingNode, RError.Message.DIMNAMES_NONARRAY); + throw invokingNode.error(RError.Message.DIMNAMES_NONARRAY); } int newDimNamesLength = newDimNames.getLength(); if (newDimNamesLength > dimensions.length) { - throw RError.error(invokingNode, RError.Message.DIMNAMES_DONT_MATCH_DIMS, newDimNamesLength, dimensions.length); + throw invokingNode.error(RError.Message.DIMNAMES_DONT_MATCH_DIMS, newDimNamesLength, dimensions.length); } for (int i = 0; i < newDimNamesLength; i++) { Object dimObject = newDimNames.getDataAt(i); if (dimObject != RNull.instance) { if (dimObject instanceof String) { if (dimensions[i] != 1) { - throw RError.error(invokingNode, RError.Message.DIMNAMES_DONT_MATCH_EXTENT, i + 1); + CompilerDirectives.transferToInterpreter(); + throw invokingNode.error(RError.Message.DIMNAMES_DONT_MATCH_EXTENT, i + 1); } } else { RStringVector dimVector = (RStringVector) dimObject; if (dimVector == null) { newDimNames.updateDataAt(i, RNull.instance, null); } else if (dimVector.getLength() != dimensions[i]) { - throw RError.error(invokingNode, RError.Message.DIMNAMES_DONT_MATCH_EXTENT, i + 1); + CompilerDirectives.transferToInterpreter(); + throw invokingNode.error(RError.Message.DIMNAMES_DONT_MATCH_EXTENT, i + 1); } } } @@ -407,8 +350,11 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement @Override public final Object getRowNames() { - Object rn = getRowNamesFromAttrs(); - return rn == null ? RNull.instance : rn; + if (attributes == null) { + return RNull.instance; + } else { + return attributes.get(RRuntime.ROWNAMES_ATTR_KEY); + } } @Override @@ -430,15 +376,15 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement return attributes == null ? false : attributes.containsKey(RRuntime.DIM_ATTR_KEY); } - public final boolean hasDimNames() { + private boolean hasDimNames() { return attributes == null ? false : attributes.containsKey(RRuntime.DIMNAMES_ATTR_KEY); } - public final boolean hasRowNames() { + private boolean hasRowNames() { return attributes == null ? false : attributes.containsKey(RRuntime.ROWNAMES_ATTR_KEY); } - public final boolean hasNames() { + private boolean hasNames() { return attributes == null ? false : attributes.containsKey(RRuntime.NAMES_ATTR_KEY); } @@ -497,10 +443,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement return setClassAttrInternal(vector, classAttr); } - public abstract class CNode extends RBaseNode { - - } - private static RAbstractContainer setClassAttrInternal(RVector<?> vector, RStringVector classAttr) { if (vector.attributes == null && classAttr != null && classAttr.getLength() != 0) { vector.initAttributes(); @@ -511,14 +453,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement for (int i = 0; i < classAttr.getLength(); i++) { String attr = classAttr.getDataAt(i); if (RRuntime.CLASS_FACTOR.equals(attr)) { - vector.putAttribute(RRuntime.CLASS_ATTR_KEY, classAttr); - if (vector.getElementClass() != RInteger.class) { - // N.B. there used to be conversion to integer under certain circumstances. - // However, it seems that it was dead/obsolete code so it was removed. - // Notes: this can only happen if the class is set by hand to some - // non-integral vector, i.e. attr(doubles, 'class') <- 'factor'. GnuR also - // does not update the 'class' attr with other, possibly - // valid classes when it reaches this error. + if (!(vector instanceof RAbstractIntVector)) { throw RError.error(RError.SHOW_CALLER2, RError.Message.ADDING_INVALID_CLASS, "factor"); } } @@ -559,34 +494,39 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement @Override public final RVector<ArrayT> copyResized(int size, boolean fillNA) { - return internalCopyResizedAndReport(size, fillNA); + RVector<ArrayT> result = internalCopyResized(size, fillNA, null); + MemoryCopyTracer.reportCopying(this, result); + return result; + } + + @Override + public final RVector<ArrayT> copyResizedWithDimensions(int[] newDimensions, boolean fillNA) { + // TODO support for higher dimensions + assert newDimensions.length == 2; + RVector<ArrayT> result = internalCopyResized(newDimensions[0] * newDimensions[1], fillNA, newDimensions); + MemoryCopyTracer.reportCopying(this, result); + return result; } // *internalCopyAndReport* methods do just the copy and report it to MemoryTracer. These should // be used if additional logic in public interface *copy* method is not desired. - protected final RVector<ArrayT> internalCopyAndReport() { + private RVector<ArrayT> internalCopyAndReport() { RVector<ArrayT> result = internalCopy(); MemoryCopyTracer.reportCopying(this, result); return result; } - protected final RVector<ArrayT> internalDeepCopyAndReport() { + private RVector<ArrayT> internalDeepCopyAndReport() { RVector<ArrayT> result = internalDeepCopy(); MemoryCopyTracer.reportCopying(this, result); return result; } - protected final RVector<ArrayT> internalCopyResizedAndReport(int size, boolean fillNA) { - RVector<ArrayT> result = internalCopyResized(size, fillNA); - MemoryCopyTracer.reportCopying(this, result); - return result; - } - // *internalCopy* methods should only be overridden, but never invoked from anywhere but // *internalCopyAndReport* - protected abstract RVector<ArrayT> internalCopyResized(int size, boolean fillNA); + protected abstract RVector<ArrayT> internalCopyResized(int size, boolean fillNA, int[] dimensions); // to be overridden by recursive structures protected RVector<ArrayT> internalDeepCopy() { @@ -595,20 +535,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement protected abstract RVector<ArrayT> internalCopy(); - @Override - public RVector<ArrayT> copyResizedWithDimensions(int[] newDimensions, boolean fillNA) { - // TODO support for higher dimensions - assert newDimensions.length == 2; - RVector<ArrayT> result = copyResized(newDimensions[0] * newDimensions[1], fillNA); - result.setDimensions(newDimensions); - return result; - } - - public final boolean verify() { - return internalVerify(); - } - - protected abstract boolean internalVerify(); + public abstract boolean verify(); /** * Update a data item in the vector. Possibly not as efficient as type-specific methods, but in @@ -648,7 +575,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement * Internal version without profiles used in a rare (and already slow) case of double-to-int * vector conversion when setting class attribute */ - protected final RAttributable copyAttributesFromVector(RVector<?> vector) { + private RAttributable copyAttributesFromVector(RVector<?> vector) { DynamicObject vecAttributes = vector.getAttributes(); if (vecAttributes != null) { initAttributes(RAttributesLayout.copy(vecAttributes)); @@ -779,32 +706,24 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement return implicitClassHeader; } - @Override - public final RShareable materializeToShareable() { - return materialize(); - } - public static void verifyDimensions(int vectorLength, int[] newDimensions, RBaseNode invokingNode) { int length = 1; for (int i = 0; i < newDimensions.length; i++) { if (RRuntime.isNA(newDimensions[i])) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(invokingNode, RError.Message.DIMS_CONTAIN_NA); + throw invokingNode.error(RError.Message.DIMS_CONTAIN_NA); } else if (newDimensions[i] < 0) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(invokingNode, RError.Message.DIMS_CONTAIN_NEGATIVE_VALUES); + throw invokingNode.error(RError.Message.DIMS_CONTAIN_NEGATIVE_VALUES); } length *= newDimensions[i]; } if (length != vectorLength && vectorLength > 0) { - CompilerDirectives.transferToInterpreter(); - throw RError.error(invokingNode, RError.Message.DIMS_DONT_MATCH_LENGTH, length, vectorLength); + throw invokingNode.error(RError.Message.DIMS_DONT_MATCH_LENGTH, length, vectorLength); } } private static final int MAX_TOSTRING_LENGTH = 100; - protected String toString(Function<Integer, String> element) { + protected final String toString(Function<Integer, String> element) { CompilerAsserts.neverPartOfCompilation(); StringBuilder str = new StringBuilder("["); for (int i = 0; i < getLength(); i++) { 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 new file mode 100644 index 0000000000000000000000000000000000000000..6f5d17a46638257c775d94e706d334cadf5426f5 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/SimpleObjectSizeFactory.java @@ -0,0 +1,87 @@ +/* + * 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.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; +import com.oracle.truffle.r.runtime.data.RObjectSize.TypeCustomizer; +import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector; +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.RAbstractRawVector; +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); + } + } + // Well known vector types + if (obj instanceof RAbstractDoubleVector) { + return Double.BYTES * ((RAbstractDoubleVector) obj).getLength(); + } else if (obj instanceof RAbstractIntVector) { + return Integer.BYTES * ((RAbstractIntVector) obj).getLength(); + } else if (obj instanceof RAbstractStringVector) { + int length = 0; + RAbstractStringVector strVec = (RAbstractStringVector) obj; + for (int i = 0; i < strVec.getLength(); i++) { + length += strVec.getDataAt(i).length(); + } + return length * 2; + } else if (obj instanceof RAbstractLogicalVector || obj instanceof RAbstractRawVector) { + return Byte.BYTES * ((RAbstractAtomicVector) obj).getLength(); + } else if (obj instanceof RAbstractListVector) { + int total = 0; + RAbstractListVector list = (RAbstractListVector) obj; + for (int i = 0; i < list.getLength(); i++) { + // Note: RLists should not be cyclic + total += getObjectSize(list.getDataAt(i), ignoreObjectHandler); + } + return total; + } + 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/data/closures/RClosures.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java index 8260e9b21a901e441fd281c74e7624324865bd01..91dddf4b5fe7e541eeaaafa46cffb8c54bd08338 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java @@ -22,19 +22,20 @@ */ package com.oracle.truffle.r.runtime.data.closures; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RDouble; -import com.oracle.truffle.r.runtime.data.RInteger; -import com.oracle.truffle.r.runtime.data.RLogical; -import com.oracle.truffle.r.runtime.data.RRaw; -import com.oracle.truffle.r.runtime.data.RString; -import com.oracle.truffle.r.runtime.data.RVector; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.data.RComplexVector; +import com.oracle.truffle.r.runtime.data.RDoubleSequence; +import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.RIntSequence; +import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RRawVector; +import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; 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.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -42,100 +43,135 @@ public class RClosures { // Logical to ... - public static RAbstractIntVector createLogicalToIntVector(RAbstractLogicalVector vector) { + public static RAbstractIntVector createToIntVector(RLogicalVector vector) { return new RLogicalToIntVectorClosure(vector); } - public static RAbstractDoubleVector createLogicalToDoubleVector(RAbstractLogicalVector vector) { + public static RAbstractDoubleVector createToDoubleVector(RLogicalVector vector) { return new RLogicalToDoubleVectorClosure(vector); } - public static RAbstractComplexVector createLogicalToComplexVector(RAbstractLogicalVector vector) { + public static RAbstractComplexVector createToComplexVector(RLogicalVector vector) { return new RLogicalToComplexVectorClosure(vector); } - public static RAbstractStringVector createLogicalToStringVector(RAbstractLogicalVector vector) { + public static RAbstractStringVector createToStringVector(RLogicalVector vector) { return new RLogicalToStringVectorClosure(vector); } + public static RAbstractListVector createToListVector(RLogicalVector vector) { + return new RLogicalToListVectorClosure(vector); + } + // Int to ... - public static RAbstractDoubleVector createIntToDoubleVector(RAbstractIntVector vector) { + public static RAbstractComplexVector createToComplexVector(RIntSequence vector) { + return new RIntSequenceToComplexVectorClosure(vector); + } + + public static RAbstractStringVector createToStringVector(RIntSequence vector) { + return new RIntSequenceToStringVectorClosure(vector); + } + + public static RAbstractListVector createToListVector(RIntSequence vector) { + return new RIntSequenceToListVectorClosure(vector); + } + + public static RAbstractDoubleVector createToDoubleVector(RIntVector vector) { return new RIntToDoubleVectorClosure(vector); } - public static RAbstractComplexVector createIntToComplexVector(RAbstractIntVector vector) { + public static RAbstractComplexVector createToComplexVector(RIntVector vector) { return new RIntToComplexVectorClosure(vector); } - public static RAbstractStringVector createIntToStringVector(RAbstractIntVector vector) { + public static RAbstractStringVector createToStringVector(RIntVector vector) { return new RIntToStringVectorClosure(vector); } + public static RAbstractListVector createToListVector(RIntVector vector) { + return new RIntToListVectorClosure(vector); + } + // Double to ... - public static RAbstractComplexVector createDoubleToComplexVector(RAbstractDoubleVector vector) { + public static RAbstractComplexVector createToComplexVector(RDoubleSequence vector) { + return new RDoubleSequenceToComplexVectorClosure(vector); + } + + public static RAbstractStringVector createToStringVector(RDoubleSequence vector) { + return new RDoubleSequenceToStringVectorClosure(vector); + } + + public static RAbstractIntVector createToIntVector(RDoubleSequence vector) { + return new RDoubleSequenceToIntVectorClosure(vector); + } + + public static RAbstractListVector createToListVector(RDoubleSequence vector) { + return new RDoubleSequenceToListVectorClosure(vector); + } + + public static RAbstractComplexVector createToComplexVector(RDoubleVector vector) { return new RDoubleToComplexVectorClosure(vector); } - public static RAbstractStringVector createDoubleToStringVector(RAbstractDoubleVector vector) { + public static RAbstractStringVector createToStringVector(RDoubleVector vector) { return new RDoubleToStringVectorClosure(vector); } - public static RAbstractIntVector createDoubleToIntVector(RAbstractDoubleVector vector) { + public static RAbstractIntVector createToIntVector(RDoubleVector vector) { return new RDoubleToIntVectorClosure(vector); } + public static RAbstractListVector createToListVector(RDoubleVector vector) { + return new RDoubleToListVectorClosure(vector); + } + // Raw to ... - public static RAbstractIntVector createRawToIntVector(RAbstractRawVector vector) { + public static RAbstractIntVector createToIntVector(RRawVector vector) { return new RRawToIntVectorClosure(vector); } - public static RAbstractDoubleVector createRawToDoubleVector(RAbstractRawVector vector) { + public static RAbstractDoubleVector createToDoubleVector(RRawVector vector) { return new RRawToDoubleVectorClosure(vector); } - public static RAbstractComplexVector createRawToComplexVector(RAbstractRawVector vector) { + public static RAbstractComplexVector createToComplexVector(RRawVector vector) { return new RRawToComplexVectorClosure(vector); } - public static RAbstractStringVector createRawToStringVector(RAbstractRawVector vector) { + public static RAbstractStringVector createToStringVector(RRawVector vector) { return new RRawToStringVectorClosure(vector); } + public static RAbstractListVector createToListVector(RRawVector vector) { + return new RRawToListVectorClosure(vector); + } + // Complex to ... - public static RAbstractStringVector createComplexToStringVector(RAbstractComplexVector vector) { + public static RAbstractStringVector createToStringVector(RComplexVector vector) { return new RComplexToStringVectorClosure(vector); } - // Vector to list + public static RAbstractListVector createToListVector(RComplexVector vector) { + return new RComplexToListVectorClosure(vector); + } + + // Character to ... - public static RAbstractListVector createAbstractVectorToListVector(RAbstractVector vector) { - return new RAbstactVectorToListClosure(vector); + public static RAbstractListVector createToListVector(RStringVector vector) { + return new RStringToListVectorClosure(vector); } // Factor to vector - public static RAbstractVector createFactorToVector(RAbstractIntVector factor, boolean withNames, RVector<?> levels) { - if (levels == null) { - return new RFactorToStringVectorClosure(factor, null, withNames); + public static RAbstractVector createFactorToVector(RAbstractIntVector factor, boolean withNames, RAbstractVector levels) { + if (levels instanceof RAbstractStringVector) { + return new RFactorToStringVectorClosure(factor, (RAbstractStringVector) levels, withNames); } else { - if (levels.getElementClass() == RInteger.class) { - return new RFactorToIntVectorClosure(factor, (RAbstractIntVector) levels, withNames); - } else if (levels.getElementClass() == RDouble.class) { - return new RFactorToDoubleVectorClosure(factor, (RAbstractDoubleVector) levels, withNames); - } else if (levels.getElementClass() == RLogical.class) { - return new RFactorToIntVectorClosure(factor, createLogicalToIntVector((RAbstractLogicalVector) levels), withNames); - } else if (levels.getElementClass() == RComplex.class) { - return new RFactorToComplexVectorClosure(factor, (RAbstractComplexVector) levels, withNames); - } else if (levels.getElementClass() == RString.class) { - return new RFactorToStringVectorClosure(factor, (RAbstractStringVector) levels, withNames); - } else { - assert levels.getElementClass() == RRaw.class; - return new RFactorToIntVectorClosure(factor, createRawToIntVector((RAbstractRawVector) levels), withNames); - } + throw RError.error(RError.SHOW_CALLER, Message.MALFORMED_FACTOR); } } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RComplexToIntVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RComplexToIntVectorClosure.java deleted file mode 100644 index 549c0338dc99746a0860e1c562c2889dbebca041..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RComplexToIntVectorClosure.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2013, 2016, 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.runtime.data.closures; - -import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; - -/** - * In converting complex numbers to integers, this closure discards the imaginary parts. - */ -final class RComplexToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector { - - RComplexToIntVectorClosure(RAbstractComplexVector vector) { - super(vector); - } - - @Override - public int getDataAt(int index) { - RComplex right = ((RAbstractComplexVector) vector).getDataAt(index); - if (!vector.isComplete() && RRuntime.isNA(right)) { - return RRuntime.INT_NA; - } - RError.warning(RError.SHOW_CALLER2, RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); - return RRuntime.complex2intNoCheck(right); - } -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RComplexToStringVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RComplexToStringVectorClosure.java deleted file mode 100644 index 136d4e7653c752a161f7afc5af630da51b1b6341..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RComplexToStringVectorClosure.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2013, 2016, 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.runtime.data.closures; - -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; - -final class RComplexToStringVectorClosure extends RToStringVectorClosure implements RAbstractStringVector { - - RComplexToStringVectorClosure(RAbstractComplexVector vector) { - super(vector); - } - - @Override - public String getDataAt(int index) { - RComplex data = ((RAbstractComplexVector) vector).getDataAt(index); - if (!vector.isComplete() && RRuntime.isNA(data)) { - return RRuntime.STRING_NA; - } - return RContext.getRRuntimeASTAccess().encodeComplex(data); - } -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToComplexVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToComplexVectorClosure.java deleted file mode 100644 index 6b9b5018e6aca98d722384f90bee933733a8c8eb..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToComplexVectorClosure.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2013, 2016, 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.runtime.data.closures; - -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; - -final class RDoubleToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector { - - private final RAbstractDoubleVector castVector; - - RDoubleToComplexVectorClosure(RAbstractDoubleVector vector) { - super(vector); - this.castVector = vector; - } - - @Override - public RComplex getDataAt(int index) { - double real = castVector.getDataAt(index); - double imaginary = 0.0; - if (Double.isNaN(real)) { - return RComplex.createNA(); - } - return RDataFactory.createComplex(real, imaginary); - } -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToIntVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToIntVectorClosure.java deleted file mode 100644 index c25c168ab9515f58cd92944377499e3cd26e81f5..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToIntVectorClosure.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2013, 2016, 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.runtime.data.closures; - -import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; - -final class RDoubleToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector { - - RDoubleToIntVectorClosure(RAbstractDoubleVector vector) { - super(vector); - } - - @Override - public int getDataAt(int index) { - double value = ((RAbstractDoubleVector) vector).getDataAt(index); - if (Double.isNaN(value)) { - return RRuntime.INT_NA; - } - int result = (int) value; - if (result == Integer.MIN_VALUE || value > Integer.MAX_VALUE) { - RError.warning(RError.SHOW_CALLER2, RError.Message.NA_INTRODUCED_COERCION); - return RRuntime.INT_NA; - } - return result; - } -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToComplexVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToComplexVectorClosure.java deleted file mode 100644 index 5826cf4d5f8a060d6dd2153ee3dbb6f05462bd94..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToComplexVectorClosure.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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 - * 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.runtime.data.closures; - -import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RIntVector; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; - -/* - * This closure is meant to be used only for implementation of the binary operators. - */ -final class RFactorToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector { - - private final RAbstractComplexVector levels; - private final boolean withNames; - - RFactorToComplexVectorClosure(RAbstractIntVector vector, RAbstractComplexVector levels, boolean withNames) { - super(vector); - assert levels != null; - this.levels = levels; - this.withNames = withNames; - } - - @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { - switch (type) { - case Character: - return new RComplexToStringVectorClosure(this); - case Complex: - return this; - default: - return null; - } - } - - @Override - public RComplex getDataAt(int index) { - int val = ((RIntVector) vector).getDataAt(index); - if (!vector.isComplete() && RRuntime.isNA(val)) { - return RRuntime.createComplexNA(); - } else { - return levels.getDataAt(val - 1); - } - } - - @Override - public RStringVector getNames() { - return withNames ? super.getNames() : null; - } -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToDoubleVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToDoubleVectorClosure.java deleted file mode 100644 index af9ed554947ed2e9c25e0a0fc493a48b9e97fb14..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToDoubleVectorClosure.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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 - * 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.runtime.data.closures; - -import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.RIntVector; -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.RAbstractVector; - -/* - * This closure is meant to be used only for implementation of the binary operators. - */ -final class RFactorToDoubleVectorClosure extends RToDoubleVectorClosure implements RAbstractDoubleVector { - - private final RAbstractDoubleVector levels; - private final boolean withNames; - - RFactorToDoubleVectorClosure(RAbstractIntVector vector, RAbstractDoubleVector levels, boolean withNames) { - super(vector); - assert levels != null; - this.levels = levels; - this.withNames = withNames; - } - - @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { - switch (type) { - case Double: - return this; - case Character: - return new RDoubleToStringVectorClosure(this); - case Complex: - return new RDoubleToComplexVectorClosure(this); - default: - return null; - } - } - - @Override - public double getDataAt(int index) { - int val = ((RIntVector) vector).getDataAt(index); - if (!vector.isComplete() && RRuntime.isNA(val)) { - return RRuntime.DOUBLE_NA; - } else { - return levels.getDataAt(val - 1); - } - } - - @Override - public RStringVector getNames() { - return withNames ? super.getNames() : null; - } -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToIntVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToIntVectorClosure.java deleted file mode 100644 index ecec033a92626bdbdfe2ee54c57aa332778f3cfe..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToIntVectorClosure.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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 - * 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.runtime.data.closures; - -import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.RType; -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.RAbstractVector; - -/* - * This closure is meant to be used only for implementation of the binary operators. - */ -final class RFactorToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector { - - private final RAbstractIntVector levels; - private final boolean withNames; - - RFactorToIntVectorClosure(RAbstractIntVector vector, RAbstractIntVector levels, boolean withNames) { - super(vector); - assert levels != null; - this.levels = levels; - this.withNames = withNames; - } - - @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { - switch (type) { - case Integer: - return this; - case Double: - return new RIntToDoubleVectorClosure(this); - case Character: - return new RIntToStringVectorClosure(this); - case Complex: - return new RIntToComplexVectorClosure(this); - default: - return null; - } - } - - @Override - public int getDataAt(int index) { - int val = ((RIntVector) vector).getDataAt(index); - if (!vector.isComplete() && RRuntime.isNA(val)) { - return RRuntime.INT_NA; - } else { - return levels.getDataAt(val - 1); - } - } - - @Override - public RStringVector getNames() { - return withNames ? super.getNames() : null; - } -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToStringVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToStringVectorClosure.java deleted file mode 100644 index 91350bfa7865c8cd21a2a108f0888b7649da21f8..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToStringVectorClosure.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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 - * 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.runtime.data.closures; - -import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.RType; -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; - -/* - * This closure is meant to be used only for implementation of the binary operators. - */ -public final class RFactorToStringVectorClosure extends RToStringVectorClosure implements RAbstractStringVector { - - private final RAbstractStringVector levels; - private final boolean withNames; - - RFactorToStringVectorClosure(RAbstractIntVector vector, RAbstractStringVector levels, boolean withNames) { - super(vector); - this.levels = levels; - this.withNames = withNames; - if (this.levels == null) { - RError.warning(RError.SHOW_CALLER2, RError.Message.IS_NA_TO_NON_VECTOR, "NULL"); - } - } - - @Override - public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { - switch (type) { - case Character: - return this; - default: - return null; - } - } - - @Override - public String getDataAt(int index) { - if (levels == null || levels.getLength() == 0) { - return RRuntime.STRING_NA; - } else { - int val = ((RIntVector) vector).getDataAt(index); - if (!vector.isComplete() && RRuntime.isNA(val)) { - return RRuntime.STRING_NA; - } else { - String l = levels.getDataAt(val - 1); - if (!levels.isComplete() && RRuntime.isNA(l)) { - return "NA"; // for comparison - } else { - return l; - } - } - } - } - - @Override - public RStringVector getNames() { - return withNames ? super.getNames() : null; - } -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToComplexVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToComplexVectorClosure.java deleted file mode 100644 index 7583e9ffc06cdee88ee5baa77d9f5adc5cf838a2..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToComplexVectorClosure.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2013, 2016, 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.runtime.data.closures; - -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; - -final class RIntToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector { - - RIntToComplexVectorClosure(RAbstractIntVector vector) { - super(vector); - } - - @Override - public RComplex getDataAt(int index) { - int data = ((RAbstractIntVector) vector).getDataAt(index); - double real; - double imaginary; - if (!vector.isComplete() && RRuntime.isNA(data)) { - real = RRuntime.COMPLEX_NA_REAL_PART; - imaginary = RRuntime.COMPLEX_NA_IMAGINARY_PART; - } else { - real = data; - imaginary = 0; - } - return RDataFactory.createComplex(real, imaginary); - } -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToComplexVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToComplexVectorClosure.java deleted file mode 100644 index 66fe09f3f36ec157aa6677329cbaba0be5165a33..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToComplexVectorClosure.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2013, 2016, 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.runtime.data.closures; - -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; - -final class RLogicalToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector { - - RLogicalToComplexVectorClosure(RAbstractLogicalVector vector) { - super(vector); - } - - @Override - public RComplex getDataAt(int index) { - byte data = ((RAbstractLogicalVector) vector).getDataAt(index); - double real; - double imaginary; - if (!vector.isComplete() && RRuntime.isNA(data)) { - real = RRuntime.COMPLEX_NA_REAL_PART; - imaginary = RRuntime.COMPLEX_NA_IMAGINARY_PART; - } else { - real = data; - imaginary = 0; - } - return RDataFactory.createComplex(real, imaginary); - } -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToDoubleVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToDoubleVectorClosure.java deleted file mode 100644 index 4a93498beaf620c8e731044d3d81ac7addc5ea47..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToDoubleVectorClosure.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2013, 2016, 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.runtime.data.closures; - -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; - -final class RLogicalToDoubleVectorClosure extends RToDoubleVectorClosure implements RAbstractDoubleVector { - - RLogicalToDoubleVectorClosure(RAbstractLogicalVector vector) { - super(vector); - } - - @Override - public double getDataAt(int index) { - byte data = ((RAbstractLogicalVector) vector).getDataAt(index); - if (!vector.isComplete() && RRuntime.isNA(data)) { - return RRuntime.DOUBLE_NA; - } - return RRuntime.logical2doubleNoCheck(data); - } -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToComplexVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToComplexVectorClosure.java index e469c8b0d07608030b4d8dc22e2a7f7e305dca14..5cad98744466bd4b3cbba1d60dd3105eca592304 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToComplexVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToComplexVectorClosure.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 @@ -22,19 +22,21 @@ */ package com.oracle.truffle.r.runtime.data.closures; +import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RComplexVector; import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RDoubleSequence; +import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.RIntSequence; +import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RRawVector; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; abstract class RToComplexVectorClosure extends RToVectorClosure implements RAbstractComplexVector { - RToComplexVectorClosure(RAbstractVector vector) { - super(vector); - } - @Override public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) { return RDataFactory.createComplexVector(new double[newLength << 1], newIsComplete); @@ -50,7 +52,7 @@ abstract class RToComplexVectorClosure extends RToVectorClosure implements RAbst result[index] = data.getRealPart(); result[index + 1] = data.getImaginaryPart(); } - return RDataFactory.createComplexVector(result, vector.isComplete()); + return RDataFactory.createComplexVector(result, getVector().isComplete()); } @Override @@ -58,3 +60,122 @@ abstract class RToComplexVectorClosure extends RToVectorClosure implements RAbst return materialize().copyWithNewDimensions(newDimensions); } } + +final class RLogicalToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector { + + private final RLogicalVector vector; + + RLogicalToComplexVectorClosure(RLogicalVector vector) { + this.vector = vector; + } + + @Override + public RLogicalVector getVector() { + return vector; + } + + @Override + public RComplex getDataAt(int index) { + byte real = vector.getDataAt(index); + return RRuntime.isNA(real) ? RComplex.createNA() : RDataFactory.createComplex(real, 0.0); + } +} + +final class RIntToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector { + + private final RIntVector vector; + + RIntToComplexVectorClosure(RIntVector vector) { + this.vector = vector; + } + + @Override + public RIntVector getVector() { + return vector; + } + + @Override + public RComplex getDataAt(int index) { + int real = vector.getDataAt(index); + return RRuntime.isNA(real) ? RComplex.createNA() : RDataFactory.createComplex(real, 0.0); + } +} + +final class RIntSequenceToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector { + + private final RIntSequence vector; + + RIntSequenceToComplexVectorClosure(RIntSequence vector) { + this.vector = vector; + } + + @Override + public RIntSequence getVector() { + return vector; + } + + @Override + public RComplex getDataAt(int index) { + int real = vector.getDataAt(index); + return RRuntime.isNA(real) ? RComplex.createNA() : RDataFactory.createComplex(real, 0.0); + } +} + +final class RDoubleToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector { + + private final RDoubleVector vector; + + RDoubleToComplexVectorClosure(RDoubleVector vector) { + this.vector = vector; + } + + @Override + public RDoubleVector getVector() { + return vector; + } + + @Override + public RComplex getDataAt(int index) { + double real = vector.getDataAt(index); + return Double.isNaN(real) ? RComplex.createNA() : RDataFactory.createComplex(real, 0.0); + } +} + +final class RDoubleSequenceToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector { + + private final RDoubleSequence vector; + + RDoubleSequenceToComplexVectorClosure(RDoubleSequence vector) { + this.vector = vector; + } + + @Override + public RDoubleSequence getVector() { + return vector; + } + + @Override + public RComplex getDataAt(int index) { + double real = vector.getDataAt(index); + return Double.isNaN(real) ? RComplex.createNA() : RDataFactory.createComplex(real, 0.0); + } +} + +final class RRawToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector { + + private final RRawVector vector; + + RRawToComplexVectorClosure(RRawVector vector) { + this.vector = vector; + } + + @Override + public RRawVector getVector() { + return vector; + } + + @Override + public RComplex getDataAt(int index) { + return RRuntime.raw2complex(vector.getDataAt(index)); + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToDoubleVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToDoubleVectorClosure.java index 55cc0daa12f45425c6a32fe8a291a56f0b9d5b64..435498a961450703b5a71b82ba97343a63c8e0a5 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToDoubleVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToDoubleVectorClosure.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 @@ -22,18 +22,18 @@ */ package com.oracle.truffle.r.runtime.data.closures; +import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.RIntSequence; +import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RRawVector; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; abstract class RToDoubleVectorClosure extends RToVectorClosure implements RAbstractDoubleVector { - RToDoubleVectorClosure(RAbstractVector vector) { - super(vector); - } - @Override public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) { return RDataFactory.createDoubleVector(new double[newLength], newIsComplete); @@ -47,7 +47,7 @@ abstract class RToDoubleVectorClosure extends RToVectorClosure implements RAbstr double data = getDataAt(i); result[i] = data; } - return RDataFactory.createDoubleVector(result, vector.isComplete()); + return RDataFactory.createDoubleVector(result, getVector().isComplete()); } @Override @@ -55,3 +55,91 @@ abstract class RToDoubleVectorClosure extends RToVectorClosure implements RAbstr return materialize().copyWithNewDimensions(newDimensions); } } + +final class RLogicalToDoubleVectorClosure extends RToDoubleVectorClosure implements RAbstractDoubleVector { + + private final RLogicalVector vector; + + RLogicalToDoubleVectorClosure(RLogicalVector vector) { + this.vector = vector; + } + + @Override + public RLogicalVector getVector() { + return vector; + } + + @Override + public double getDataAt(int index) { + byte data = vector.getDataAt(index); + if (RRuntime.isNA(data)) { + return RRuntime.DOUBLE_NA; + } + return RRuntime.logical2doubleNoCheck(data); + } +} + +final class RIntToDoubleVectorClosure extends RToDoubleVectorClosure implements RAbstractDoubleVector { + + private final RIntVector vector; + + RIntToDoubleVectorClosure(RIntVector vector) { + this.vector = vector; + } + + @Override + public RIntVector getVector() { + return vector; + } + + @Override + public double getDataAt(int index) { + int data = vector.getDataAt(index); + if (RRuntime.isNA(data)) { + return RRuntime.DOUBLE_NA; + } + return RRuntime.int2doubleNoCheck(data); + } +} + +final class RIntSequenceToDoubleVectorClosure extends RToDoubleVectorClosure implements RAbstractDoubleVector { + + private final RIntSequence vector; + + RIntSequenceToDoubleVectorClosure(RIntSequence vector) { + this.vector = vector; + } + + @Override + public RIntSequence getVector() { + return vector; + } + + @Override + public double getDataAt(int index) { + int data = vector.getDataAt(index); + if (RRuntime.isNA(data)) { + return RRuntime.DOUBLE_NA; + } + return RRuntime.int2doubleNoCheck(data); + } +} + +final class RRawToDoubleVectorClosure extends RToDoubleVectorClosure implements RAbstractDoubleVector { + + private final RRawVector vector; + + RRawToDoubleVectorClosure(RRawVector vector) { + this.vector = vector; + } + + @Override + public RRawVector getVector() { + return vector; + } + + @Override + public double getDataAt(int index) { + return RRuntime.raw2double(vector.getDataAt(index)); + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToIntVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToIntVectorClosure.java index 132946950c1687bf8b1a42f9b3ca342a1f4aba19..187b1260e7fcfd8951a4f6ec9346a295471144a3 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToIntVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToIntVectorClosure.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 @@ -22,18 +22,21 @@ */ package com.oracle.truffle.r.runtime.data.closures; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.RComplex; +import com.oracle.truffle.r.runtime.data.RComplexVector; import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RDoubleSequence; +import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RRawVector; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; abstract class RToIntVectorClosure extends RToVectorClosure implements RAbstractIntVector { - RToIntVectorClosure(RAbstractVector vector) { - super(vector); - } - @Override public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) { return RDataFactory.createIntVector(new int[newLength], newIsComplete); @@ -47,7 +50,7 @@ abstract class RToIntVectorClosure extends RToVectorClosure implements RAbstract int data = getDataAt(i); result[i] = data; } - return RDataFactory.createIntVector(result, vector.isComplete()); + return RDataFactory.createIntVector(result, getVector().isComplete()); } @Override @@ -55,3 +58,128 @@ abstract class RToIntVectorClosure extends RToVectorClosure implements RAbstract return materialize().copyWithNewDimensions(newDimensions); } } + +final class RLogicalToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector { + + private final RLogicalVector vector; + + RLogicalToIntVectorClosure(RLogicalVector vector) { + this.vector = vector; + } + + @Override + public RLogicalVector getVector() { + return vector; + } + + @Override + public int getDataAt(int index) { + byte data = vector.getDataAt(index); + if (RRuntime.isNA(data)) { + return RRuntime.INT_NA; + } + return data; + } +} + +final class RDoubleToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector { + + private final RDoubleVector vector; + + RDoubleToIntVectorClosure(RDoubleVector vector) { + this.vector = vector; + } + + @Override + public RDoubleVector getVector() { + return vector; + } + + @Override + public int getDataAt(int index) { + double value = vector.getDataAt(index); + if (Double.isNaN(value)) { + return RRuntime.INT_NA; + } + int result = (int) value; + if (result == Integer.MIN_VALUE || value > Integer.MAX_VALUE) { + RError.warning(RError.SHOW_CALLER2, RError.Message.NA_INTRODUCED_COERCION); + return RRuntime.INT_NA; + } + return result; + } +} + +final class RDoubleSequenceToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector { + + private final RDoubleSequence vector; + + RDoubleSequenceToIntVectorClosure(RDoubleSequence vector) { + this.vector = vector; + } + + @Override + public RDoubleSequence getVector() { + return vector; + } + + @Override + public int getDataAt(int index) { + double value = vector.getDataAt(index); + if (Double.isNaN(value)) { + return RRuntime.INT_NA; + } + int result = (int) value; + if (result == Integer.MIN_VALUE || value > Integer.MAX_VALUE) { + RError.warning(RError.SHOW_CALLER2, RError.Message.NA_INTRODUCED_COERCION); + return RRuntime.INT_NA; + } + return result; + } +} + +/** + * In converting complex numbers to integers, this closure discards the imaginary parts. + */ +final class RComplexToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector { + + private final RComplexVector vector; + + RComplexToIntVectorClosure(RComplexVector vector) { + this.vector = vector; + } + + @Override + public RComplexVector getVector() { + return vector; + } + + @Override + public int getDataAt(int index) { + RComplex right = vector.getDataAt(index); + if (RRuntime.isNA(right)) { + return RRuntime.INT_NA; + } + RError.warning(RError.SHOW_CALLER2, RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION); + return RRuntime.complex2intNoCheck(right); + } +} + +final class RRawToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector { + + private final RRawVector vector; + + RRawToIntVectorClosure(RRawVector vector) { + this.vector = vector; + } + + @Override + public RRawVector getVector() { + return vector; + } + + @Override + public int getDataAt(int index) { + return RRuntime.raw2int(vector.getDataAt(index)); + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToListVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToListVectorClosure.java new file mode 100644 index 0000000000000000000000000000000000000000..8a03a34c89bb72bc9b4f3e8ecf5b98c502ab0ace --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToListVectorClosure.java @@ -0,0 +1,220 @@ +/* + * 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 + * 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.runtime.data.closures; + +import com.oracle.truffle.r.runtime.data.RComplex; +import com.oracle.truffle.r.runtime.data.RComplexVector; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RDoubleSequence; +import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.RIntSequence; +import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RRaw; +import com.oracle.truffle.r.runtime.data.RRawVector; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.RVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +abstract class RToListVectorClosure extends RToVectorClosure implements RAbstractListVector { + + @Override + public Object getDataAtAsObject(int index) { + return getDataAt(index); + } + + @Override + public RList materialize() { + int length = getLength(); + Object[] result = new Object[length]; + for (int i = 0; i < length; i++) { + Object data = getDataAt(i); + result[i] = data; + } + return RDataFactory.createList(result); + } + + @Override + public RAbstractVector copyWithNewDimensions(int[] newDimensions) { + return materialize().copyWithNewDimensions(newDimensions); + } + + @Override + public RVector<?> createEmptySameType(int newLength, boolean newIsComplete) { + return RDataFactory.createList(new Object[newLength]); + } +} + +final class RLogicalToListVectorClosure extends RToListVectorClosure { + + private final RLogicalVector vector; + + RLogicalToListVectorClosure(RLogicalVector vector) { + this.vector = vector; + } + + @Override + public RLogicalVector getVector() { + return vector; + } + + @Override + public Byte getDataAt(int index) { + return vector.getDataAt(index); + } +} + +final class RIntToListVectorClosure extends RToListVectorClosure { + + private final RIntVector vector; + + RIntToListVectorClosure(RIntVector vector) { + this.vector = vector; + } + + @Override + public RIntVector getVector() { + return vector; + } + + @Override + public Integer getDataAt(int index) { + return vector.getDataAt(index); + } +} + +final class RIntSequenceToListVectorClosure extends RToListVectorClosure { + + private final RIntSequence vector; + + RIntSequenceToListVectorClosure(RIntSequence vector) { + this.vector = vector; + } + + @Override + public RIntSequence getVector() { + return vector; + } + + @Override + public Integer getDataAt(int index) { + return vector.getDataAt(index); + } +} + +final class RDoubleToListVectorClosure extends RToListVectorClosure { + + private final RDoubleVector vector; + + RDoubleToListVectorClosure(RDoubleVector vector) { + this.vector = vector; + } + + @Override + public RDoubleVector getVector() { + return vector; + } + + @Override + public Double getDataAt(int index) { + return vector.getDataAt(index); + } +} + +final class RDoubleSequenceToListVectorClosure extends RToListVectorClosure { + + private final RDoubleSequence vector; + + RDoubleSequenceToListVectorClosure(RDoubleSequence vector) { + this.vector = vector; + } + + @Override + public RDoubleSequence getVector() { + return vector; + } + + @Override + public Double getDataAt(int index) { + return vector.getDataAt(index); + } +} + +final class RComplexToListVectorClosure extends RToListVectorClosure { + + private final RComplexVector vector; + + RComplexToListVectorClosure(RComplexVector vector) { + this.vector = vector; + } + + @Override + public RComplexVector getVector() { + return vector; + } + + @Override + public RComplex getDataAt(int index) { + return vector.getDataAt(index); + } +} + +final class RStringToListVectorClosure extends RToListVectorClosure { + + private final RStringVector vector; + + RStringToListVectorClosure(RStringVector vector) { + this.vector = vector; + } + + @Override + public RStringVector getVector() { + return vector; + } + + @Override + public String getDataAt(int index) { + return vector.getDataAt(index); + } +} + +final class RRawToListVectorClosure extends RToListVectorClosure { + + private final RRawVector vector; + + RRawToListVectorClosure(RRawVector vector) { + this.vector = vector; + } + + @Override + public RRawVector getVector() { + return vector; + } + + @Override + public RRaw getDataAt(int index) { + return vector.getDataAt(index); + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java index 6db80a38ca6ed75d5ed8106df5c86f1f82307da4..e9a127adbd78625542c2c120db0d0964957c899e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java @@ -23,18 +23,27 @@ package com.oracle.truffle.r.runtime.data.closures; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RComplex; +import com.oracle.truffle.r.runtime.data.RComplexVector; import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RDoubleSequence; +import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.RIntSequence; +import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RRawVector; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RVector; +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; abstract class RToStringVectorClosure extends RToVectorClosure implements RAbstractStringVector { - RToStringVectorClosure(RAbstractVector vector) { - super(vector); - } - @Override public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) { return RDataFactory.createStringVector(new String[newLength], newIsComplete); @@ -48,7 +57,7 @@ abstract class RToStringVectorClosure extends RToVectorClosure implements RAbstr String data = getDataAt(i); result[i] = data; } - return RDataFactory.createStringVector(result, vector.isComplete(), getDimensionsMaterialized(), getNamesMaterialized()); + return RDataFactory.createStringVector(result, getVector().isComplete(), getDimensionsMaterialized(), getNamesMaterialized()); } @TruffleBoundary @@ -66,3 +75,214 @@ abstract class RToStringVectorClosure extends RToVectorClosure implements RAbstr return materialize().copyWithNewDimensions(newDimensions); } } + +final class RLogicalToStringVectorClosure extends RToStringVectorClosure { + + private final RLogicalVector vector; + + RLogicalToStringVectorClosure(RLogicalVector vector) { + this.vector = vector; + } + + @Override + public RLogicalVector getVector() { + return vector; + } + + @Override + public String getDataAt(int index) { + byte data = vector.getDataAt(index); + if (!vector.isComplete() && RRuntime.isNA(data)) { + return RRuntime.STRING_NA; + } + return RRuntime.logicalToStringNoCheck(data); + + } +} + +final class RIntToStringVectorClosure extends RToStringVectorClosure { + + private final RIntVector vector; + + RIntToStringVectorClosure(RIntVector vector) { + this.vector = vector; + } + + @Override + public RIntVector getVector() { + return vector; + } + + @Override + public String getDataAt(int index) { + int data = vector.getDataAt(index); + if (!vector.isComplete() && RRuntime.isNA(data)) { + return RRuntime.STRING_NA; + } + return RRuntime.intToStringNoCheck(data); + } +} + +final class RIntSequenceToStringVectorClosure extends RToStringVectorClosure { + + private final RIntSequence vector; + + RIntSequenceToStringVectorClosure(RIntSequence vector) { + this.vector = vector; + } + + @Override + public RIntSequence getVector() { + return vector; + } + + @Override + public String getDataAt(int index) { + int data = vector.getDataAt(index); + if (!vector.isComplete() && RRuntime.isNA(data)) { + return RRuntime.STRING_NA; + } + return RRuntime.intToStringNoCheck(data); + } +} + +final class RDoubleToStringVectorClosure extends RToStringVectorClosure { + + private final RDoubleVector vector; + + RDoubleToStringVectorClosure(RDoubleVector vector) { + this.vector = vector; + } + + @Override + public RDoubleVector getVector() { + return vector; + } + + @Override + public String getDataAt(int index) { + double data = vector.getDataAt(index); + if (!vector.isComplete() && RRuntime.isNA(data)) { + return RRuntime.STRING_NA; + } else { + return RContext.getRRuntimeASTAccess().encodeDouble(data); + } + } +} + +final class RDoubleSequenceToStringVectorClosure extends RToStringVectorClosure { + + private final RDoubleSequence vector; + + RDoubleSequenceToStringVectorClosure(RDoubleSequence vector) { + this.vector = vector; + } + + @Override + public RDoubleSequence getVector() { + return vector; + } + + @Override + public String getDataAt(int index) { + double data = vector.getDataAt(index); + if (!vector.isComplete() && RRuntime.isNA(data)) { + return RRuntime.STRING_NA; + } else { + return RContext.getRRuntimeASTAccess().encodeDouble(data); + } + } +} + +final class RComplexToStringVectorClosure extends RToStringVectorClosure { + + private final RComplexVector vector; + + RComplexToStringVectorClosure(RComplexVector vector) { + this.vector = vector; + } + + @Override + public RComplexVector getVector() { + return vector; + } + + @Override + public String getDataAt(int index) { + RComplex data = vector.getDataAt(index); + if (!vector.isComplete() && RRuntime.isNA(data)) { + return RRuntime.STRING_NA; + } + return RContext.getRRuntimeASTAccess().encodeComplex(data); + } +} + +final class RRawToStringVectorClosure extends RToStringVectorClosure { + + private final RRawVector vector; + + RRawToStringVectorClosure(RRawVector vector) { + this.vector = vector; + } + + @Override + public RRawVector getVector() { + return vector; + } + + @Override + public String getDataAt(int index) { + return RRuntime.rawToString(vector.getDataAt(index)); + } +} + +/* + * This closure is meant to be used only for implementation of the binary operators. + */ +final class RFactorToStringVectorClosure extends RToStringVectorClosure { + + private final RAbstractIntVector vector; + private final RAbstractStringVector levels; + private final boolean withNames; + + RFactorToStringVectorClosure(RAbstractIntVector vector, RAbstractStringVector levels, boolean withNames) { + this.vector = vector; + this.levels = levels; + this.withNames = withNames; + } + + @Override + public RAbstractIntVector getVector() { + return vector; + } + + @Override + public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) { + switch (type) { + case Character: + return this; + default: + return null; + } + } + + @Override + public String getDataAt(int index) { + int val = ((RIntVector) vector).getDataAt(index); + if (!vector.isComplete() && RRuntime.isNA(val)) { + return RRuntime.STRING_NA; + } else { + String l = levels.getDataAt(val - 1); + if (!levels.isComplete() && RRuntime.isNA(l)) { + return "NA"; // for comparison + } else { + return l; + } + } + } + + @Override + public RStringVector getNames() { + return withNames ? super.getNames() : null; + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java index 1f17428efc272e49b1dad966bbd8602176b5841c..9d00bf9472669b9f2513206cfe1f9856c987bbe6 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java @@ -23,9 +23,8 @@ package com.oracle.truffle.r.runtime.data.closures; import com.oracle.truffle.api.object.DynamicObject; -import com.oracle.truffle.r.runtime.data.MemoryCopyTracer; +import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.data.RVector; @@ -34,15 +33,11 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; abstract class RToVectorClosure implements RAbstractVector { - protected final RAbstractVector vector; - - RToVectorClosure(RAbstractVector vector) { - this.vector = vector; - } + public abstract RAbstractVector getVector(); @Override public int getLength() { - return vector.getLength(); + return getVector().getLength(); } @Override @@ -52,147 +47,122 @@ abstract class RToVectorClosure implements RAbstractVector { @Override public final RAbstractContainer resize(int size) { - return vector.resize(size); + return getVector().resize(size); } @Override public final void setComplete(boolean complete) { - this.vector.setComplete(complete); + this.getVector().setComplete(complete); } @Override public final boolean isComplete() { - return vector.isComplete(); + return getVector().isComplete(); } @Override public final boolean hasDimensions() { - return vector.hasDimensions(); + return getVector().hasDimensions(); } @Override public final int[] getDimensions() { - return vector.getDimensions(); + return getVector().getDimensions(); } @Override public final void setDimensions(int[] newDimensions) { - vector.setDimensions(newDimensions); + getVector().setDimensions(newDimensions); } @Override public RStringVector getNames() { - return vector.getNames(); + return getVector().getNames(); } @Override public final void setNames(RStringVector newNames) { - vector.setNames(newNames); + getVector().setNames(newNames); } @Override public final RList getDimNames() { - return vector.getDimNames(); + return getVector().getDimNames(); } @Override public final void setDimNames(RList newDimNames) { - vector.setDimNames(newDimNames); + getVector().setDimNames(newDimNames); } @Override public final Object getRowNames() { - return vector.getRowNames(); + return getVector().getRowNames(); } @Override public final void setRowNames(RAbstractVector rowNames) { - vector.setRowNames(rowNames); + getVector().setRowNames(rowNames); } @Override public final DynamicObject initAttributes() { - return vector.initAttributes(); + return getVector().initAttributes(); } @Override public final void initAttributes(DynamicObject newAttributes) { - vector.initAttributes(newAttributes); + getVector().initAttributes(newAttributes); } @Override public final DynamicObject getAttributes() { - return vector.getAttributes(); + return getVector().getAttributes(); } @Override public final RAbstractVector copy() { - RAbstractVector result = vector.copy(); - MemoryCopyTracer.reportCopying(this, result); - return result; + throw RInternalError.shouldNotReachHere(); } @Override public final RVector<?> copyResized(int size, boolean fillNA) { - RVector<?> result = vector.copyResized(size, fillNA); - MemoryCopyTracer.reportCopying(this, result); - return result; + throw RInternalError.shouldNotReachHere(); } @Override public final RVector<?> copyResizedWithDimensions(int[] newDimensions, boolean fillNA) { - // TODO support for higher dimensions - assert newDimensions.length == 2; - RVector<?> result = copyResized(newDimensions[0] * newDimensions[1], fillNA); - result.setDimensions(newDimensions); - return result; + throw RInternalError.shouldNotReachHere(); } @Override public final RAbstractVector copyDropAttributes() { - RAbstractVector result = vector.copyDropAttributes(); - MemoryCopyTracer.reportCopying(this, result); - return result; + throw RInternalError.shouldNotReachHere(); } @Override public final boolean isMatrix() { - return vector.isMatrix(); + return getVector().isMatrix(); } @Override public final boolean isArray() { - return vector.isArray(); - } - - @Override - public final RStringVector getClassHierarchy() { - return vector.getClassHierarchy(); - } - - @Override - public RStringVector getImplicitClass() { - return vector.getImplicitClass(); + return getVector().isArray(); } @Override public final RTypedValue getNonShared() { - return vector.getNonShared(); - } - - @Override - public final RShareable materializeToShareable() { - return vector.materialize(); + return getVector().getNonShared(); } @Override public int getTypedValueInfo() { - return vector.getTypedValueInfo(); + return getVector().getTypedValueInfo(); } @Override public void setTypedValueInfo(int value) { - vector.setTypedValueInfo(value); + getVector().setTypedValueInfo(value); } @Override diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractAtomicVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractAtomicVector.java index 839804eb00977d5f6b0de425e5a232f2b5e428cc..bb039d34c6815f2c8d5c56ef0c750e23ff4f54e9 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractAtomicVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractAtomicVector.java @@ -22,9 +22,6 @@ */ package com.oracle.truffle.r.runtime.data.model; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.r.runtime.data.RTypesFlatLayout; - /** * Distinguishes what R considers an "atomic" vector, e.g. {@code integer()} from other "vectors", * e.g., {@code list()}. Specifically these are the FastR atomic vector types: @@ -36,8 +33,6 @@ import com.oracle.truffle.r.runtime.data.RTypesFlatLayout; * <li>{@link RAbstractStringVector}</li> * <li>{@link RAbstractRawVector}</li> * </ul> - * - * N.B. To use this in a {@link Specialization} you must use {@link RTypesFlatLayout}. */ public interface RAbstractAtomicVector extends RAbstractVector { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractComplexVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractComplexVector.java index 3ad93d63f6978b9cc587d5fbd5573e5f34cc991d..b2d9e6cd06d0ad7e508393bfe0f29004d3e6f8f4 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractComplexVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractComplexVector.java @@ -62,9 +62,4 @@ public interface RAbstractComplexVector extends RAbstractAtomicVector { default RType getRType() { return RType.Complex; } - - @Override - default Class<?> getElementClass() { - return RComplex.class; - } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java index a3001eaf5da0f4d603b89e626078bc2a917f2d84..5afbae372907df8ac0f98640c8a71f1ce1a17f66 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java @@ -26,7 +26,6 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RTypedValue; @@ -44,11 +43,9 @@ public interface RAbstractContainer extends RAttributable, RTypedValue { void setDimensions(int[] newDimensions); - Class<?> getElementClass(); - RTypedValue getNonShared(); - RShareable materializeToShareable(); + RAbstractContainer materialize(); Object getDataAtAsObject(int index); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractDoubleVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractDoubleVector.java index 8bfd1573077131338384384b95014682a898dc7a..ab8c782a3f97d0e8882eb8d551d50debf22905f0 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractDoubleVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractDoubleVector.java @@ -24,7 +24,6 @@ package com.oracle.truffle.r.runtime.data.model; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.RDouble; import com.oracle.truffle.r.runtime.data.RDoubleVector; public interface RAbstractDoubleVector extends RAbstractAtomicVector { @@ -62,9 +61,4 @@ public interface RAbstractDoubleVector extends RAbstractAtomicVector { default RType getRType() { return RType.Double; } - - @Override - default Class<?> getElementClass() { - return RDouble.class; - } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractIntVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractIntVector.java index bc64990d6114804f91779463a367bd057c302b27..92401aea21e6a7f5a42f0c130ab62b3c716806ce 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractIntVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractIntVector.java @@ -25,7 +25,6 @@ package com.oracle.truffle.r.runtime.data.model; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RIntVector; -import com.oracle.truffle.r.runtime.data.RInteger; public interface RAbstractIntVector extends RAbstractAtomicVector { @@ -62,9 +61,4 @@ public interface RAbstractIntVector extends RAbstractAtomicVector { default RType getRType() { return RType.Integer; } - - @Override - default Class<?> getElementClass() { - return RInteger.class; - } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractListBaseVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractListBaseVector.java index edd08c2347b8d0ed755d8e46f1abb0b5e52cd4c7..31ceb508163554eedbe07f546c1465c37e938657 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractListBaseVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractListBaseVector.java @@ -34,18 +34,13 @@ public interface RAbstractListBaseVector extends RAbstractVector { Object getDataAt(int index); - @Override - default boolean checkCompleteness() { - return true; - } - - @Override - default Class<?> getElementClass() { - return Object.class; - } - @SuppressWarnings("unused") default void setDataAt(Object store, int index, Object value) { throw new UnsupportedOperationException(); } + + @Override + default boolean checkCompleteness() { + return true; + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractListVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractListVector.java index 681861e7e5429f2649ad951488a43344072548ef..46c3406328d76d832607d20cdcbae80713604a8b 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractListVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractListVector.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 @@ -25,6 +25,9 @@ package com.oracle.truffle.r.runtime.data.model; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RList; +/** + * Note: lists must not contain {@code null} values. + */ public interface RAbstractListVector extends RAbstractListBaseVector { @Override diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractLogicalVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractLogicalVector.java index abb58b0adb2308d62398abacb6137218b404d86e..2a1c503de5361dcd250c061344b5c621f97c0e8a 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractLogicalVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractLogicalVector.java @@ -24,7 +24,6 @@ package com.oracle.truffle.r.runtime.data.model; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.RLogical; import com.oracle.truffle.r.runtime.data.RLogicalVector; public interface RAbstractLogicalVector extends RAbstractAtomicVector { @@ -62,9 +61,4 @@ public interface RAbstractLogicalVector extends RAbstractAtomicVector { default RType getRType() { return RType.Logical; } - - @Override - default Class<?> getElementClass() { - return RLogical.class; - } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractRawVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractRawVector.java index 38441f5fb118b2c322746bf2f024ff842c49dec8..202f841cd2d6879829b6652a98ef6c93e2c858e9 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractRawVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractRawVector.java @@ -58,9 +58,4 @@ public interface RAbstractRawVector extends RAbstractAtomicVector { default RType getRType() { return RType.Raw; } - - @Override - default Class<?> getElementClass() { - return RRaw.class; - } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractStringVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractStringVector.java index 032c8bed11216dd37a72c1670fc29b547e421436..af93f141e09f2791c2e7fcc4b809b2302ce22355 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractStringVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractStringVector.java @@ -24,7 +24,6 @@ package com.oracle.truffle.r.runtime.data.model; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.RString; import com.oracle.truffle.r.runtime.data.RStringVector; public interface RAbstractStringVector extends RAbstractAtomicVector { @@ -62,9 +61,4 @@ public interface RAbstractStringVector extends RAbstractAtomicVector { default RType getRType() { return RType.Character; } - - @Override - default Class<?> getElementClass() { - return RString.class; - } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java index bf9862638a626303dc8de30cc24939053b470b14..2d16b9fbeaaadc411d77f097171a685915f6d079 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java @@ -53,6 +53,7 @@ public interface RAbstractVector extends RAbstractContainer { RVector<?> createEmptySameType(int newLength, boolean newIsComplete); + @Override RVector<?> materialize(); boolean isMatrix(); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java index 4cf0176368423fa63a183ba02c9c5747a1331e2a..b8ba2fe1c75518f24ba5f714d69ba7077ecbbd99 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java @@ -29,6 +29,7 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.runtime.AnonymousFrameVariable; @@ -41,6 +42,7 @@ import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.VirtualEvalFrame; import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.context.RContext.ContextKind; import com.oracle.truffle.r.runtime.data.RAttributeStorage; import com.oracle.truffle.r.runtime.data.RAttributesLayout; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -48,6 +50,7 @@ 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.RStringVector; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.env.frame.NSBaseMaterializedFrame; import com.oracle.truffle.r.runtime.env.frame.REnvEmptyFrameAccess; import com.oracle.truffle.r.runtime.env.frame.REnvFrameAccess; @@ -105,13 +108,6 @@ import com.oracle.truffle.r.runtime.env.frame.REnvTruffleFrameAccess; */ public abstract class REnvironment extends RAttributeStorage { - private static final RStringVector implicitClass = RDataFactory.createStringVectorFromScalar(RType.Environment.getName()); - - @Override - public final RStringVector getImplicitClass() { - return implicitClass; - } - public static final class ContextStateImpl implements RContext.ContextState { private final MaterializedFrame globalFrame; @CompilationFinal private Base baseEnv; @@ -159,8 +155,15 @@ public abstract class REnvironment extends RAttributeStorage { beforeDestroyContext(context, this); } - public static ContextStateImpl newContextState() { - return new ContextStateImpl(RRuntime.createNonFunctionFrame("global")); + public static ContextStateImpl newContextState(RContext context) { + MaterializedFrame newGlobalFrame; + if (context.getKind() == ContextKind.SHARE_ALL) { + ContextStateImpl parentState = context.getParent().stateREnvironment; + newGlobalFrame = parentState.getGlobalFrame(); + } else { + newGlobalFrame = RRuntime.createNonFunctionFrame("global"); + } + return new ContextStateImpl(newGlobalFrame); } public void initialize(Base newBaseEnv, REnvironment newNamespaceRegistry, SearchPath newSearchPath) { @@ -336,6 +339,7 @@ public abstract class REnvironment extends RAttributeStorage { /* We make shallow copies of all the default package environments in the parent */ ContextStateImpl parentState = context.getParent().stateREnvironment; SearchPath parentSearchPath = parentState.getSearchPath(); + assert parentSearchPath.size() > 1; // clone all the environments below global from the parent REnvironment e = parentSearchPath.get(1).cloneEnv(globalFrame); // create the new Global with clone top as parent @@ -359,6 +363,15 @@ public abstract class REnvironment extends RAttributeStorage { break; } + case SHARE_ALL: { + ContextStateImpl parentState = context.getParent().stateREnvironment; + // TODO: may be worthwhile to assert for all environments on the search path there + // is 1:1 descriptor:frame mapping (as they are all meant to be shared in we rely on + // the single descriptor information to identify accesses to shared frames) + contextState.initialize(parentState.getBaseEnv(), parentState.getNamespaceRegistry(), parentState.getSearchPath()); + break; + } + case SHARE_NOTHING: { // SHARE_NOTHING: baseInitialize takes care of everything break; @@ -754,7 +767,7 @@ public abstract class REnvironment extends RAttributeStorage { */ public void setParent(REnvironment env) { if (getParent() != env) { - RArguments.setEnclosingFrame(getFrame(), env.getFrame()); + RArguments.setEnclosingFrame(getFrame(), env.getFrame(), true); } } @@ -897,6 +910,32 @@ public abstract class REnvironment extends RAttributeStorage { return getPrintName(); } + public static void convertSearchpathToMultiSlot() { + CompilerAsserts.neverPartOfCompilation(); + RContext.markNonSingle(); + ContextStateImpl parentState = RContext.getInstance().stateREnvironment; + SearchPath searchPath = parentState.getSearchPath(); + assert searchPath.size() > 0 && searchPath.get(0).getSearchName() == Global.SEARCHNAME; + // for global space don't replicate entries as all contexts should see their own values + FrameSlotChangeMonitor.handleAllMultiSlots(searchPath.get(0).getFrame(), false); + for (int i = 1; i < searchPath.size(); i++) { + FrameSlotChangeMonitor.handleAllMultiSlots(searchPath.get(i).getFrame(), true); + } + REnvironment namespaces = parentState.namespaceRegistry; + Frame namespacesFrame = namespaces.getFrame(); + // make a copy avoid potential updates to the array iterated over + FrameSlot[] slots = new FrameSlot[namespacesFrame.getFrameDescriptor().getSlots().size()]; + slots = namespacesFrame.getFrameDescriptor().getSlots().toArray(slots); + for (int i = 0; i < slots.length; i++) { + REnvironment namespaceEnv = (REnvironment) namespacesFrame.getValue(slots[i]); + if (namespaceEnv != Base.baseNamespaceEnv()) { + // base namespace frame redirects all accesses to base frame and this would + // result in processing the slots twice + FrameSlotChangeMonitor.handleAllMultiSlots(namespaceEnv.getFrame(), true); + } + } + } + private static final class BaseNamespace extends REnvironment { private BaseNamespace(String name, MaterializedFrame frame) { super(name, frame); 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 new file mode 100644 index 0000000000000000000000000000000000000000..d44fd73c8796a4725c679e55032c7030a1be91f6 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java @@ -0,0 +1,345 @@ +/* + * 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 + * 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.runtime.env; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.Message; +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.interop.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.metadata.ScopeProvider.AbstractScope; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RArguments; +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.env.REnvironment.PutException; + +/** + * Represents a variable scope for external tools like a debugger.<br> + * This is basically a view on R environments. + */ +public final class RScope extends AbstractScope { + + private final Node current; + private REnvironment env; + + /** + * Intended to be used when creating a parent scope where we do not know any associated node. + */ + private RScope(REnvironment env) { + this.env = env; + this.current = null; + } + + private RScope(Node current, REnvironment env) { + this.current = current; + this.env = env; + } + + @Override + protected String getName() { + // just to be sure + if (env == REnvironment.emptyEnv()) { + return "empty environment"; + } + + assert env.getFrame() != null; + RFunction function = RArguments.getFunction(env.getFrame()); + if (function != null) { + String name = function.getName(); + return "function environment" + (name != null ? " for function " + name : ""); + } else { + String name = env.getName(); + return "explicit environment" + (name != null ? ": " + name : ""); + } + } + + @Override + protected Node getNode() { + return current; + } + + @Override + protected Object getVariables(Frame frame) { + return new VariablesMapObject(env, false); + } + + private static REnvironment getEnv(Frame frame) { + assert RArguments.isRFrame(frame); + return REnvironment.frameToEnvironment(frame.materialize()); + } + + @Override + protected Object getArguments(Frame frame) { + return new VariablesMapObject(env, true); + } + + @Override + protected AbstractScope findParent() { + if (this.env == REnvironment.emptyEnv()) { + return null; + } + + return new RScope(env.getParent()); + } + + private static String[] ls(REnvironment env) { + RStringVector ls = env.ls(true, null, false); + return ls.getDataWithoutCopying(); + } + + private static String[] collectArgs(REnvironment env) { + + if (env != REnvironment.emptyEnv()) { + assert RArguments.isRFrame(env.getFrame()); + RFunction f = RArguments.getFunction(env.getFrame()); + if (f != null) { + return RContext.getRRuntimeASTAccess().getArgumentsSignature(f).getNames(); + } else { + ArgumentsSignature suppliedSignature = RArguments.getSuppliedSignature(env.getFrame()); + if (suppliedSignature != null) { + return suppliedSignature.getNames(); + } + } + } + return new String[0]; + } + + public static RScope createScope(Node node, Frame frame) { + return new RScope(node.getRootNode(), getEnv(frame)); + } + + private static Object getInteropValue(Object value) { + return value; + } + + static final class VariablesMapObject implements TruffleObject { + + private final REnvironment env; + private final boolean argumentsOnly; + + private VariablesMapObject(REnvironment env, boolean argumentsOnly) { + this.env = env; + this.argumentsOnly = argumentsOnly; + } + + @Override + public ForeignAccess getForeignAccess() { + return VariablesMapMessageResolutionForeign.ACCESS; + } + + public static boolean isInstance(TruffleObject obj) { + return obj instanceof VariablesMapObject; + } + + @MessageResolution(receiverType = VariablesMapObject.class) + static final class VariablesMapMessageResolution { + + @Resolve(message = "KEYS") + abstract static class VarsMapKeysNode extends Node { + + @TruffleBoundary + public Object access(VariablesMapObject varMap) { + if (varMap.argumentsOnly) { + return new ArgumentNamesObject(collectArgs(varMap.env)); + } else { + return new VariableNamesObject(varMap.env); + } + } + } + + @Resolve(message = "KEY_INFO") + public abstract static class VarMapsKeyInfoNode extends Node { + + private static final int READABLE = 1 << 1; + private static final int WRITABLE = 1 << 2; + private static final int INVOCABLE = 1 << 3; + + @SuppressWarnings("try") + protected Object access(VariablesMapObject receiver, String identifier) { + int info = READABLE; + + if (!receiver.env.bindingIsLocked(identifier)) { + info += WRITABLE; + } + if (receiver.env.get(identifier) instanceof RFunction) { + info += INVOCABLE; + } + return info; + } + } + + @Resolve(message = "READ") + abstract static class VarsMapReadNode extends Node { + + @TruffleBoundary + public Object access(VariablesMapObject varMap, String name) { + if (varMap.env == null) { + throw UnsupportedMessageException.raise(Message.READ); + } + Object value = varMap.env.get(name); + + // If Java-null is returned, the identifier does not exist ! + if (value == null) { + throw UnknownIdentifierException.raise(name); + } else { + return getInteropValue(value); + } + } + } + + @Resolve(message = "WRITE") + abstract static class VarsMapWriteNode extends Node { + + @TruffleBoundary + public Object access(VariablesMapObject varMap, String name, Object value) { + if (varMap.env == null) { + throw UnsupportedMessageException.raise(Message.WRITE); + } + try { + varMap.env.put(name, value); + return value; + } catch (PutException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + } + + } + } + + 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; + + private ArgumentNamesObject(String[] names) { + this.names = names; + } + + @Override + public ForeignAccess getForeignAccess() { + return ArgumentNamesMessageResolutionForeign.ACCESS; + } + + public static boolean isInstance(TruffleObject obj) { + return obj instanceof ArgumentNamesObject; + } + + @MessageResolution(receiverType = ArgumentNamesObject.class) + static final class ArgumentNamesMessageResolution { + + @Resolve(message = "HAS_SIZE") + abstract static class ArgNamesHasSizeNode extends Node { + + @SuppressWarnings("unused") + public Object access(ArgumentNamesObject varNames) { + return true; + } + } + + @Resolve(message = "GET_SIZE") + abstract static class ArgNamesGetSizeNode extends Node { + + public Object access(ArgumentNamesObject varNames) { + return varNames.names.length; + } + } + + @Resolve(message = "READ") + abstract static class ArgNamesReadNode extends Node { + + @TruffleBoundary + public Object access(ArgumentNamesObject varNames, int index) { + if (index >= 0 && index < varNames.names.length) { + return varNames.names[index]; + } else { + throw UnknownIdentifierException.raise(Integer.toString(index)); + } + } + } + + } + } + +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java new file mode 100644 index 0000000000000000000000000000000000000000..f44d5c5222baf7632708d894ec6e08fea8c74a7f --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java @@ -0,0 +1,74 @@ +/* + * 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 + * 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.runtime.env.frame; + +import java.util.Objects; + +import com.oracle.truffle.r.runtime.RCaller; +import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RTruffleObject; +import com.oracle.truffle.r.runtime.env.REnvironment; + +/** + * Represent an active binding of a function. This requires special treatment when reading and + * writing variables. + */ +public class ActiveBinding implements RTruffleObject { + + private final RType expectedType; + private final RFunction function; + + public ActiveBinding(RType expectedType, RFunction fun) { + this.expectedType = Objects.requireNonNull(expectedType); + this.function = Objects.requireNonNull(fun); + } + + public RFunction getFunction() { + return function; + } + + public RType getExpectedType() { + return expectedType; + } + + public static boolean isActiveBinding(Object binding) { + return binding instanceof ActiveBinding; + } + + @Override + public String toString() { + return "active binding"; + } + + public Object writeValue(Object value) { + return RContext.getEngine().evalFunction(function, REnvironment.baseEnv().getFrame(), RCaller.createInvalid(null), null, value); + } + + public Object readValue() { + return RContext.getEngine().evalFunction(function, REnvironment.baseEnv().getFrame(), RCaller.createInvalid(null), RDataFactory.createEmptyStringVector()); + } + +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java index 8455c58c0cfc800c59c6c75c67e4db142cee5a14..8c7e60ef51c8b7702fac9021c1b41902a2c9d1fa 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.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 @@ -35,17 +35,22 @@ import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; +import com.oracle.truffle.api.frame.FrameSlotTypeException; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.nodes.InvalidAssumptionException; import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.StableValue; +import com.oracle.truffle.r.runtime.context.ContextInfo; +import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RPromise; /** @@ -146,7 +151,7 @@ public final class FrameSlotChangeMonitor { public Object getValue() { // fast path execution should use getFrame / getSlot CompilerAsserts.neverPartOfCompilation("FrameAndSlotLookupResult.getValue() should not be used in fast path execution"); - return frame.getValue(slot); + return FrameSlotChangeMonitor.getValue(slot, frame); } public MaterializedFrame getFrame() throws InvalidAssumptionException { @@ -169,7 +174,7 @@ public final class FrameSlotChangeMonitor { private static final class FrameDescriptorMetaData { private final String name; // name for debug purposes private final WeakReference<MaterializedFrame> singletonFrame; - private final Set<FrameDescriptor> subDescriptors = Collections.newSetFromMap(new WeakHashMap<>()); + private final Set<FrameDescriptor> subDescriptors = Collections.newSetFromMap(new WeakHashMap<>(2)); /** * This set contains all lookups that have been performed "across" this frame descriptor. If @@ -180,10 +185,11 @@ public final class FrameSlotChangeMonitor { /** * A set of all lookups that started in this frame descriptor. */ - private final WeakHashMap<Object, WeakReference<LookupResult>> lookupResults = new WeakHashMap<>(); + private final WeakHashMap<Object, WeakReference<LookupResult>> lookupResults = new WeakHashMap<>(2); private WeakReference<FrameDescriptor> enclosingFrameDescriptor = new WeakReference<>(null); private Assumption enclosingFrameDescriptorAssumption = Truffle.getRuntime().createAssumption("enclosing frame descriptor"); + private Assumption containsNoActiveBindingAssumption = Truffle.getRuntime().createAssumption("contains no active binding"); private FrameDescriptorMetaData(String name, MaterializedFrame singletonFrame) { this.name = name; @@ -208,6 +214,10 @@ public final class FrameSlotChangeMonitor { public Assumption getEnclosingFrameDescriptorAssumption() { return enclosingFrameDescriptorAssumption; } + + public Assumption getContainsNoActiveBindingAssumption() { + return containsNoActiveBindingAssumption; + } } private static final WeakHashMap<FrameDescriptor, FrameDescriptorMetaData> frameDescriptors = new WeakHashMap<>(); @@ -236,6 +246,7 @@ public final class FrameSlotChangeMonitor { } else { FrameDescriptorMetaData currentMetaData = getMetaData(current); if (currentMetaData.singletonFrame == null) { + // no stable value and no singleton frame return null; } else { assert currentMetaData.singletonFrame.get() != null; @@ -306,7 +317,8 @@ public final class FrameSlotChangeMonitor { return frame == null ? null : frame instanceof NSBaseMaterializedFrame ? ((NSBaseMaterializedFrame) frame).getMarkerFrameDescriptor() : frame.getFrameDescriptor(); } - private static FrameDescriptorMetaData getMetaData(FrameDescriptor descriptor) { + private static synchronized FrameDescriptorMetaData getMetaData(FrameDescriptor descriptor) { + CompilerAsserts.neverPartOfCompilation(); FrameDescriptorMetaData result = frameDescriptors.get(descriptor); assert result != null : "null metadata for " + descriptor; return result; @@ -446,6 +458,24 @@ public final class FrameSlotChangeMonitor { // System.out.println(String.format(format, args)); } + public static final class MultiSlotData { + + private final Object[] data = new Object[ContextInfo.contextNum()]; + + public Object get(int ind) { + return data[ind]; + } + + public void set(int ind, Object val) { + data[ind] = val; + } + + public void setAll(Object val) { + Arrays.fill(data, val); + } + + } + private static final class FrameSlotInfoImpl { /** * This is meant to monitor updates performed on {@link FrameSlot}. Each {@link FrameSlot} @@ -458,11 +488,14 @@ public final class FrameSlotChangeMonitor { * comes into play.<br/> */ private final Assumption nonLocalModifiedAssumption = Truffle.getRuntime().createAssumption(); + private final Assumption noMultiSlot = Truffle.getRuntime().createAssumption(); - @CompilationFinal private StableValue<Object> stableValue; + @CompilationFinal private volatile StableValue<Object> stableValue; private int invalidationCount; + private final boolean possibleMultiSlot; - FrameSlotInfoImpl(boolean isSingletonFrame, boolean isGlobalEnv, Object identifier) { + FrameSlotInfoImpl(boolean isSingletonFrame, boolean isGlobalEnv, Object identifier, boolean isNewEnv) { + this.possibleMultiSlot = isSingletonFrame && !isNewEnv; if (isSingletonFrame) { stableValue = new StableValue<>(null, identifier.toString()); invalidationCount = isGlobalEnv ? MAX_GLOBAL_ENV_INVALIDATION_COUNT : MAX_INVALIDATION_COUNT; @@ -475,37 +508,52 @@ public final class FrameSlotChangeMonitor { return stableValue != null; } + public boolean possibleMultiSlot() { + return possibleMultiSlot; + } + /* * Special cases for primitive types to force value (instead of identity) comparison. */ - public void setValue(byte value, FrameSlot slot) { - if (stableValue != null && (!(stableValue.getValue() instanceof Byte) || ((byte) stableValue.getValue()) != value)) { - invalidateStableValue(value, slot); + private void setValue(boolean value, FrameSlot slot) { + StableValue<Object> sv = stableValue; + if (sv != null && (!(sv.getValue() instanceof Boolean) || ((boolean) sv.getValue()) != value)) { + invalidateStableValue(sv, value, slot); } } - public void setValue(int value, FrameSlot slot) { - if (stableValue != null && (!(stableValue.getValue() instanceof Integer) || ((int) stableValue.getValue()) != value)) { - invalidateStableValue(value, slot); + private void setValue(byte value, FrameSlot slot) { + StableValue<Object> sv = stableValue; + if (sv != null && (!(sv.getValue() instanceof Byte) || ((byte) sv.getValue()) != value)) { + invalidateStableValue(sv, value, slot); } } - public void setValue(double value, FrameSlot slot) { - if (stableValue != null && (!(stableValue.getValue() instanceof Double) || ((double) stableValue.getValue()) != value)) { - invalidateStableValue(value, slot); + private void setValue(int value, FrameSlot slot) { + StableValue<Object> sv = stableValue; + if (sv != null && (!(sv.getValue() instanceof Integer) || ((int) sv.getValue()) != value)) { + invalidateStableValue(sv, value, slot); } } - public void setValue(Object value, FrameSlot slot) { - if (stableValue != null && stableValue.getValue() != value) { - invalidateStableValue(value, slot); + private void setValue(double value, FrameSlot slot) { + StableValue<Object> sv = stableValue; + if (sv != null && (!(sv.getValue() instanceof Double) || ((double) sv.getValue()) != value)) { + invalidateStableValue(sv, value, slot); } } - private void invalidateStableValue(Object value, FrameSlot slot) { + private void setValue(Object value, FrameSlot slot) { + StableValue<Object> sv = stableValue; + if (sv != null && sv.getValue() != value) { + invalidateStableValue(sv, value, slot); + } + } + + private void invalidateStableValue(StableValue<Object> sv, Object value, FrameSlot slot) { CompilerDirectives.transferToInterpreterAndInvalidate(); - stableValue.getAssumption().invalidate(); + sv.getAssumption().invalidate(); if (invalidationCount > 0) { invalidationCount--; out("setting singleton value %s = %s", slot.getIdentifier(), value == null ? "null" : value.getClass()); @@ -519,6 +567,110 @@ public final class FrameSlotChangeMonitor { public StableValue<Object> getStableValue() { return stableValue; } + + private static void setNewMultiValue(Frame frame, FrameSlot slot, MultiSlotData data, Object newValue) { + int ind = RContext.getInstance().getMultiSlotInd(); + data.set(ind, newValue); + frame.setObject(slot, data); + } + + private static boolean evalAndSetPromise(Frame frame, FrameSlot slot, FrameSlotInfoImpl info) { + Object prevValue = info.stableValue.getValue(); + if (prevValue instanceof RPromise) { + prevValue = RContext.getRRuntimeASTAccess().forcePromise("searchPathPromiseForce", prevValue); + if (prevValue instanceof Boolean) { + frame.setBoolean(slot, (boolean) prevValue); + info.setValue((boolean) prevValue, slot); + } else if (prevValue instanceof Byte) { + frame.setByte(slot, (byte) prevValue); + info.setValue((byte) prevValue, slot); + } else if (prevValue instanceof Integer) { + frame.setInt(slot, (int) prevValue); + info.setValue((int) prevValue, slot); + } else if (prevValue instanceof Double) { + frame.setDouble(slot, (double) prevValue); + info.setValue((double) prevValue, slot); + } else { + frame.setObject(slot, prevValue); + info.setValue(prevValue, slot); + } + return true; + } else { + return false; + } + } + + public static void handleSearchPathMultiSlot(Frame frame, FrameSlot slot, boolean replicate) { + CompilerAsserts.neverPartOfCompilation(); + while (true) { + FrameSlotInfoImpl info = (FrameSlotInfoImpl) slot.getInfo(); + if (info.stableValue == null || !replicate) { + // create a multi slot for slots whose stableValue is null but also for all + // slots of + // the global frame (which are marked as !replicate) + info.stableValue = null; + info.nonLocalModifiedAssumption.invalidate(); + info.noMultiSlot.invalidate(); + info.invalidationCount = 0; + MultiSlotData data = new MultiSlotData(); + Object prevValue = frame.getValue(slot); + // TODO: do we have to worry that prevValue can be invalid? + if (prevValue instanceof MultiSlotData) { + // this handles the case when we create share contexts for the second time - + // existing multi slots are an artifact of the previous executions and must + // be + // discarded + // TOOD: consider re-using multi slots but since we don't expect many of + // them, + // perhaps it's too much work for too little gain + prevValue = ((MultiSlotData) prevValue).get(0); + } else if (FastROptions.SearchPathForcePromises.getBooleanValue()) { + prevValue = RContext.getRRuntimeASTAccess().forcePromise("searchPathPromiseForce", prevValue); + } + if (replicate) { + data.setAll(prevValue); + } else { + data.set(0, prevValue); + } + frame.setObject(slot, data); + break; + } else { + if (!FastROptions.SearchPathForcePromises.getBooleanValue() || !evalAndSetPromise(frame, slot, info)) { + break; + } + // otherwise stable value may get nullified and slot turned into multi slot + } + + } + } + + @TruffleBoundary + public synchronized void setMultiSlot(Frame frame, FrameSlot slot, Object newValue) { + // TODO: perhaps putting the whole thing behind the Truffle boundary an overkill, but on + // the other hand it shouldn't happen often and not on the fast path + MultiSlotData data; + if (stableValue == null) { + // already a multi slot - should be visible to all threads + data = (MultiSlotData) frame.getValue(slot); + int ind = RContext.getInstance().getMultiSlotInd(); + data.set(ind, newValue); + } else { + nonLocalModifiedAssumption.invalidate(); + invalidationCount = 0; + // TODO: is it necessary since we nullify stable value? + stableValue.getAssumption().invalidate(); + noMultiSlot.invalidate(); + data = new MultiSlotData(); + Object prevValue = frame.getValue(slot); + // value was stable so this slot is set by primordial context + data.set(0, prevValue); + setNewMultiValue(frame, slot, data, newValue); + // this should create happens-before with stable value reads during lookup, thus + // making preceding update to the actual frame OK to read without additional + // synchronization + stableValue = null; + } + } } /** @@ -534,22 +686,32 @@ public final class FrameSlotChangeMonitor { Object info = slot.getInfo(); if (!(info instanceof FrameSlotInfoImpl)) { CompilerDirectives.transferToInterpreter(); - throw RInternalError.shouldNotReachHere("Each FrameSlot should hold a FrameSlotInfo in its info field!"); + throw RInternalError.shouldNotReachHere("Each FrameSlot should hold a FrameSlotInfo in its info field! " + slot.getIdentifier().getClass() + " " + slot.getIdentifier()); } return (FrameSlotInfoImpl) info; } // methods for creating new frame slots - public static synchronized FrameSlot findOrAddFrameSlot(FrameDescriptor fd, Object identifier, FrameSlotKind initialKind) { + public static FrameSlot findOrAddFrameSlot(FrameDescriptor fd, String identifier, FrameSlotKind initialKind) { + return findOrAddFrameSlot(fd, (Object) identifier, initialKind); + } + + public static FrameSlot findOrAddFrameSlot(FrameDescriptor fd, RFrameSlot identifier, FrameSlotKind initialKind) { + return findOrAddFrameSlot(fd, (Object) identifier, initialKind); + } + + private static synchronized FrameSlot findOrAddFrameSlot(FrameDescriptor fd, Object identifier, FrameSlotKind initialKind) { CompilerAsserts.neverPartOfCompilation(); + assert identifier instanceof String || identifier instanceof RFrameSlot; FrameSlot frameSlot = fd.findFrameSlot(identifier); if (frameSlot != null) { return frameSlot; } else { FrameDescriptorMetaData metaData = getMetaData(fd); invalidateNames(metaData, Arrays.asList(identifier)); - return fd.addFrameSlot(identifier, new FrameSlotInfoImpl(metaData.singletonFrame != null, "global".equals(metaData.name), identifier), initialKind); + return fd.addFrameSlot(identifier, new FrameSlotInfoImpl(metaData.singletonFrame != null, "global".equals(metaData.name), identifier, metaData.name.startsWith("<new-env-")), + initialKind); } } @@ -579,40 +741,135 @@ public final class FrameSlotChangeMonitor { } } + public static void setBooleanAndInvalidate(Frame frame, FrameSlot frameSlot, boolean newValue, boolean isNonLocal, BranchProfile invalidateProfile) { + FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot); + if (FastROptions.SharedContexts.getBooleanValue() && info.possibleMultiSlot() && !RContext.isSingle()) { + info.setMultiSlot(frame, frameSlot, newValue); + } else { + frame.setBoolean(frameSlot, newValue); + if (info.needsInvalidation()) { + info.setValue(newValue, frameSlot); + } + checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile); + } + } + + public static void setBoolean(Frame frame, FrameSlot frameSlot, boolean newValue) { + if (FastROptions.SharedContexts.getBooleanValue() && !RContext.isSingle()) { + FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot); + if (info.possibleMultiSlot()) { + info.setMultiSlot(frame, frameSlot, newValue); + return; + } + } + frame.setBoolean(frameSlot, newValue); + } + public static void setByteAndInvalidate(Frame frame, FrameSlot frameSlot, byte newValue, boolean isNonLocal, BranchProfile invalidateProfile) { - frame.setByte(frameSlot, newValue); FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot); - if (info.needsInvalidation()) { - info.setValue(newValue, frameSlot); + if (FastROptions.SharedContexts.getBooleanValue() && info.possibleMultiSlot() && !RContext.isSingle()) { + info.setMultiSlot(frame, frameSlot, newValue); + } else { + frame.setByte(frameSlot, newValue); + if (info.needsInvalidation()) { + info.setValue(newValue, frameSlot); + } + checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile); } - checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile); + } + + public static void setByte(Frame frame, FrameSlot frameSlot, byte newValue) { + if (FastROptions.SharedContexts.getBooleanValue() && !RContext.isSingle()) { + FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot); + if (info.possibleMultiSlot()) { + info.setMultiSlot(frame, frameSlot, newValue); + return; + } + } + frame.setByte(frameSlot, newValue); } public static void setIntAndInvalidate(Frame frame, FrameSlot frameSlot, int newValue, boolean isNonLocal, BranchProfile invalidateProfile) { - frame.setInt(frameSlot, newValue); FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot); - if (info.needsInvalidation()) { - info.setValue(newValue, frameSlot); + if (FastROptions.SharedContexts.getBooleanValue() && info.possibleMultiSlot() && !RContext.isSingle()) { + info.setMultiSlot(frame, frameSlot, newValue); + } else { + frame.setInt(frameSlot, newValue); + if (info.needsInvalidation()) { + info.setValue(newValue, frameSlot); + } + checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile); } - checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile); + } + + public static void setInt(Frame frame, FrameSlot frameSlot, int newValue) { + if (FastROptions.SharedContexts.getBooleanValue() && !RContext.isSingle()) { + FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot); + if (info.possibleMultiSlot()) { + info.setMultiSlot(frame, frameSlot, newValue); + return; + } + } + frame.setInt(frameSlot, newValue); } public static void setDoubleAndInvalidate(Frame frame, FrameSlot frameSlot, double newValue, boolean isNonLocal, BranchProfile invalidateProfile) { - frame.setDouble(frameSlot, newValue); FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot); - if (info.needsInvalidation()) { - info.setValue(newValue, frameSlot); + if (FastROptions.SharedContexts.getBooleanValue() && info.possibleMultiSlot() && !RContext.isSingle()) { + info.setMultiSlot(frame, frameSlot, newValue); + } else { + frame.setDouble(frameSlot, newValue); + if (info.needsInvalidation()) { + info.setValue(newValue, frameSlot); + } + checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile); } - checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile); + } + + public static void setDouble(Frame frame, FrameSlot frameSlot, double newValue) { + if (FastROptions.SharedContexts.getBooleanValue() && !RContext.isSingle()) { + FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot); + if (info.possibleMultiSlot()) { + info.setMultiSlot(frame, frameSlot, newValue); + return; + } + } + frame.setDouble(frameSlot, newValue); } public static void setObjectAndInvalidate(Frame frame, FrameSlot frameSlot, Object newValue, boolean isNonLocal, BranchProfile invalidateProfile) { + assert !ActiveBinding.isActiveBinding(newValue); + FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot); + if (FastROptions.SharedContexts.getBooleanValue() && info.possibleMultiSlot() && !RContext.isSingle()) { + info.setMultiSlot(frame, frameSlot, newValue); + } else { + frame.setObject(frameSlot, newValue); + if (info.needsInvalidation()) { + info.setValue(newValue, frameSlot); + } + checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile); + } + } + + public static void setObject(Frame frame, FrameSlot frameSlot, Object newValue) { + if (FastROptions.SharedContexts.getBooleanValue() && !RContext.isSingle()) { + FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot); + if (info.possibleMultiSlot()) { + info.setMultiSlot(frame, frameSlot, newValue); + return; + } + } + frame.setObject(frameSlot, newValue); + } + + public static void setActiveBinding(Frame frame, FrameSlot frameSlot, ActiveBinding newValue, boolean isNonLocal, BranchProfile invalidateProfile) { frame.setObject(frameSlot, newValue); FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot); if (info.needsInvalidation()) { info.setValue(newValue, frameSlot); } checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile); + getContainsNoActiveBindingAssumption(frame.getFrameDescriptor()).invalidate(); } /** @@ -620,11 +877,14 @@ public final class FrameSlotChangeMonitor { * intended to be used for a non-function frame (and thus will only ever be used for one frame). */ public static synchronized void initializeNonFunctionFrameDescriptor(String name, MaterializedFrame frame) { + CompilerAsserts.neverPartOfCompilation(); frameDescriptors.put(handleBaseNamespaceEnv(frame), new FrameDescriptorMetaData(name, frame)); } - public static synchronized void initializeFunctionFrameDescriptor(String name, FrameDescriptor frameDescriptor) { + public static synchronized FrameDescriptor initializeFunctionFrameDescriptor(String name, FrameDescriptor frameDescriptor) { + CompilerAsserts.neverPartOfCompilation(); frameDescriptors.put(frameDescriptor, new FrameDescriptorMetaData(name, null)); + return frameDescriptor; } public static synchronized Assumption getEnclosingFrameDescriptorAssumption(FrameDescriptor descriptor) { @@ -632,6 +892,11 @@ public final class FrameSlotChangeMonitor { return frameDescriptors.get(descriptor).getEnclosingFrameDescriptorAssumption(); } + public static synchronized Assumption getContainsNoActiveBindingAssumption(FrameDescriptor descriptor) { + CompilerAsserts.neverPartOfCompilation(); + return frameDescriptors.get(descriptor).getContainsNoActiveBindingAssumption(); + } + public static synchronized StableValue<Object> getStableValueAssumption(FrameDescriptor descriptor, FrameSlot frameSlot, Object value) { CompilerAsserts.neverPartOfCompilation(); StableValue<Object> stableValue = getFrameSlotInfo(frameSlot).getStableValue(); @@ -651,4 +916,62 @@ public final class FrameSlotChangeMonitor { public static boolean isValidFrameDescriptor(FrameDescriptor frameDesc) { return getMetaData(frameDesc) != null; } + + /* + * This method should be called for frames of all environments on the search path. + */ + public static void handleAllMultiSlots(Frame frame, boolean replicate) { + // make a copy avoid potential updates to the array iterated over + FrameSlot[] slots = new FrameSlot[frame.getFrameDescriptor().getSlots().size()]; + slots = frame.getFrameDescriptor().getSlots().toArray(slots); + for (int i = 0; i < slots.length; i++) { + if (!(slots[i].getIdentifier() instanceof RFrameSlot)) { + FrameSlotInfoImpl.handleSearchPathMultiSlot(frame, slots[i], replicate); + } + } + } + + public static Object getObject(FrameSlot slot, Frame frame) throws FrameSlotTypeException { + if (FastROptions.SharedContexts.getBooleanValue() && !RContext.isSingle()) { + FrameSlotInfoImpl info = getFrameSlotInfo(slot); + if (info.noMultiSlot.isValid()) { + return frame.getObject(slot); + } + Object o; + try { + o = frame.getObject(slot); + } catch (FrameSlotTypeException e) { + CompilerDirectives.transferToInterpreter(); + o = null; + } + if (!(o instanceof MultiSlotData)) { + CompilerDirectives.transferToInterpreter(); + synchronized (info) { + o = frame.getObject(slot); + } + } + return ((MultiSlotData) o).get(RContext.getInstance().getMultiSlotInd()); + } else { + return frame.getObject(slot); + } + } + + public static Object getValue(FrameSlot slot, Frame frame) { + if (FastROptions.SharedContexts.getBooleanValue() && !RContext.isSingle()) { + FrameSlotInfoImpl info = getFrameSlotInfo(slot); + if (info.noMultiSlot.isValid()) { + return frame.getValue(slot); + } + Object o = frame.getValue(slot); + if (!(o instanceof MultiSlotData)) { + CompilerDirectives.transferToInterpreter(); + synchronized (info) { + o = frame.getValue(slot); + } + } + return ((MultiSlotData) o).get(RContext.getInstance().getMultiSlotInd()); + } else { + return frame.getValue(slot); + } + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java index af7d7af6ec7e74c8c527523e9c58216cd6736c29..e7006cbd06fb44eee613d651621de8cd08e5c778 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.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 @@ -60,7 +60,7 @@ public final class NSBaseMaterializedFrame implements MaterializedFrame { } public void updateGlobalFrame(MaterializedFrame globalFrame) { - RArguments.setEnclosingFrame(this, globalFrame); + RArguments.setEnclosingFrame(this, globalFrame, true); } public FrameDescriptor getMarkerFrameDescriptor() { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java index da58110d0b4a622e7d3f3bbae954b875d1e08e81..d6d1b687c96a339e268f9952692ea4f5074d3143 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.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 @@ -33,6 +33,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; +import com.oracle.truffle.api.frame.FrameSlotTypeException; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; @@ -65,12 +66,18 @@ public final class REnvTruffleFrameAccess extends REnvFrameAccess { @Override public Object get(String key) { + CompilerAsserts.neverPartOfCompilation(); FrameDescriptor fd = frame.getFrameDescriptor(); FrameSlot slot = fd.findFrameSlot(key); if (slot == null) { return null; } else { - return frame.getValue(slot); + Object value = FrameSlotChangeMonitor.getValue(slot, frame); + // special treatment for active binding: call bound function + if (ActiveBinding.isActiveBinding(value)) { + return ((ActiveBinding) value).readValue(); + } + return value; } } @@ -103,7 +110,18 @@ public final class REnvTruffleFrameAccess extends REnvFrameAccess { FrameSlotChangeMonitor.setDoubleAndInvalidate(frame, slot, (double) value, false, null); break; case Object: - FrameSlotChangeMonitor.setObjectAndInvalidate(frame, slot, value, false, null); + Object object; + try { + object = frame.getObject(slot); + } catch (FrameSlotTypeException e) { + object = null; + } + + if (object != null && ActiveBinding.isActiveBinding(object)) { + ((ActiveBinding) object).writeValue(value); + } else { + FrameSlotChangeMonitor.setObjectAndInvalidate(frame, slot, value, false, null); + } break; case Illegal: break; @@ -142,7 +160,8 @@ public final class REnvTruffleFrameAccess extends REnvFrameAccess { ArrayList<String> matchedNamesList = new ArrayList<>(names.length); for (int i = 0; i < names.length; i++) { String name = names[i]; - if (frame.getValue(fd.findFrameSlot(name)) == null) { + FrameSlot frameSlot = fd.findFrameSlot(name); + if (FrameSlotChangeMonitor.getValue(frameSlot, frame) == null) { continue; } if (REnvironment.includeName(name, allNames, pattern)) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/RFrameSlot.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/RFrameSlot.java index e303fac170654063244a601a7b1891c87fb7e9cb..9b407b153627a1b7e4a5f18813f3589f0ccbe64f 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/RFrameSlot.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/RFrameSlot.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 @@ -31,12 +31,37 @@ import com.oracle.truffle.r.runtime.nodes.RNode; * Description of different internal frame slots used by FastR. This enum is used as an identifier, * so that these internal frame slots have non-string names. */ -public enum RFrameSlot { +public final class RFrameSlot { + private final String name; + private final boolean multiSlot; + + private RFrameSlot(String name, boolean multiSlot) { + this.name = name; + this.multiSlot = multiSlot; + } + + @Override + public String toString() { + return name == null ? "TempFrameSlot" : name; + } + + public boolean isTemp() { + return name == null; + } + + public boolean isMultiSlot() { + return multiSlot; + } + + public static RFrameSlot createTemp(boolean multiSlot) { + return new RFrameSlot(null, multiSlot); + } + /** * This frame slot is used to store expressions installed as function exit handlers via on.exit. * It contains an {@link ArrayList} with {@link RNode} elements. */ - OnExit, + public static final RFrameSlot OnExit = new RFrameSlot("OnExit", false); /** * This frame slot is used to track result visibility. It can contain one of three values: * <ul> @@ -51,13 +76,17 @@ public enum RFrameSlot { * each call site, the value of {@link RCaller#getVisibility()} is extracted and stored into the * frame slot. */ - Visibility, + public static final RFrameSlot Visibility = new RFrameSlot("Visibility", false); /** * Used to save the handler stack in frames that modify it. */ - HandlerStack, + public static final RFrameSlot HandlerStack = new RFrameSlot("HandlerStack", false); /** * Used to save the restart stack in frames that modify it. */ - RestartStack + public static final RFrameSlot RestartStack = new RFrameSlot("RestartStack", false); + + public static RFrameSlot[] values() { + return new RFrameSlot[]{OnExit, Visibility, HandlerStack, RestartStack}; + } } 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 00825a42b45ddb1fd518cc46d09cd67265ba48aa..2bb5d9a64ae5afc53428ec640de1594bb98a051a 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 @@ -309,12 +309,16 @@ public class DLL { * 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 * single VM, so the class is defined as a "union" for simplicity. + * + * N.B. It is explicitly allowed to register a {@code null} value as the base package registers + * some (Fortran) functions that are implemented in Java but have a bogus (zero) native symbol + * definition. Any use of {@code null} is failed */ public static final class SymbolHandle { public final Object value; public SymbolHandle(Object value) { - assert value instanceof Long || value instanceof TruffleObject; + assert value == null || value instanceof Long || value instanceof TruffleObject; this.value = value; } @@ -577,6 +581,7 @@ public class DLL { @Child RFindSymbolNode findSymbolNode = RFindSymbolNode.create(); + @SuppressWarnings("deprecation") private RFindSymbolRootNode() { super(RContext.getRRuntimeASTAccess().getTruffleRLanguage(), null, new FrameDescriptor()); } @@ -616,9 +621,11 @@ public class DLL { return f; } - if (!dllInfo.dynamicLookup) { - return SYMBOL_NOT_FOUND; - } + // TODO: there is a weird interaction with namespace environments that makes this not + // true in all cases + // if (!dllInfo.dynamicLookup) { + // return SYMBOL_NOT_FOUND; + // } String mName = name; // assume Fortran underscore, although GnuR has cc code for this diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java index a8f3622fa426a6c5a8d5070705abf8a160e4ed08..30632fc5d3d2457910993d77303c3e236f829171 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.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 @@ -30,65 +30,178 @@ import com.oracle.truffle.api.nodes.Node; * the result of the call. */ public interface LapackRFFI { - abstract class LapackRFFINode extends Node { + abstract class IlaverNode extends Node { /** * Return version info, mjor, minor, patch, in {@code version}. */ - public abstract void ilaver(int[] version); + public abstract void execute(int[] version); + public static IlaverNode create() { + return RFFIFactory.getRFFI().getLapackRFFI().createIlaverNode(); + } + } + + abstract class DgeevNode extends Node { /** * See <a href="http://www.netlib.org/lapack/explore-html/d9/d28/dgeev_8f.html">spec</a>. */ - public abstract int dgeev(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork); + public abstract int execute(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork); + + public static DgeevNode create() { + return RFFIFactory.getRFFI().getLapackRFFI().createDgeevNode(); + } + } + abstract class Dgeqp3Node extends Node { /** * See <a href="http://www.netlib.org/lapack/explore-html/db/de5/dgeqp3_8f.html">spec</a>. */ - public abstract int dgeqp3(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork); + public abstract int execute(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork); + + public static Dgeqp3Node create() { + return RFFIFactory.getRFFI().getLapackRFFI().createDgeqp3Node(); + } + } + abstract class DormqrNode extends Node { /** * See <a href="http://www.netlib.org/lapack/explore-html/da/d82/dormqr_8f.html">spec</a>. */ - public abstract int dormqr(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork); + public abstract int execute(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork); + + public static DormqrNode create() { + return RFFIFactory.getRFFI().getLapackRFFI().createDormqrNode(); + } + } + + abstract class DtrtrsNode extends Node { /** * See <a href="http://www.netlib.org/lapack/explore-html/d6/d6f/dtrtrs_8f.html">spec</a>. */ - public abstract int dtrtrs(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb); + public abstract int execute(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb); + + public static DtrtrsNode create() { + return RFFIFactory.getRFFI().getLapackRFFI().createDtrtrsNode(); + } + } + + abstract class DgetrfNode extends Node { /** * See <a href="http://www.netlib.org/lapack/explore-html/d3/d6a/dgetrf_8f.html">spec</a>. */ - public abstract int dgetrf(int m, int n, double[] a, int lda, int[] ipiv); + public abstract int execute(int m, int n, double[] a, int lda, int[] ipiv); + + public static DgetrfNode create() { + return RFFIFactory.getRFFI().getLapackRFFI().createDgetrfNode(); + } + } + + abstract class DpotrfNode extends Node { /** * See <a href="http://www.netlib.org/lapack/explore-html/d0/d8a/dpotrf_8f.html">spec</a>. */ - public abstract int dpotrf(char uplo, int n, double[] a, int lda); + public abstract int execute(char uplo, int n, double[] a, int lda); + + public static DpotrfNode create() { + return RFFIFactory.getRFFI().getLapackRFFI().createDpotrfNode(); + } + } + + abstract class DpotriNode extends Node { + + /** + * See <a href="http://www.netlib.org/lapack/explore-html/d0/d8a/dpotri_8f.html">spec</a>. + */ + public abstract int execute(char uplo, int n, double[] a, int lda); + public static DpotriNode create() { + return RFFIFactory.getRFFI().getLapackRFFI().createDpotriNode(); + } + } + + abstract class DpstrfNode extends Node { /** * See <a href="http://www.netlib.org/lapack/explore-html/dd/dad/dpstrf_8f.html">spec</a>. */ - public abstract int dpstrf(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work); + public abstract int execute(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work); + + public static DpstrfNode create() { + return RFFIFactory.getRFFI().getLapackRFFI().createDpstrfNode(); + } + } + abstract class DgesvNode extends Node { /** * See <a href="http://www.netlib.org/lapack/explore-html/d8/d72/dgesv_8f.html">spec</a>. */ - public abstract int dgesv(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb); + public abstract int execute(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb); + + public static DgesvNode create() { + return RFFIFactory.getRFFI().getLapackRFFI().createDgesvNode(); + } + } + + abstract class DlangeNode extends Node { /** * See <a href="http://www.netlib.org/lapack/explore-html/dc/d09/dlange_8f.html">spec</a>. */ - public abstract double dlange(char norm, int m, int n, double[] a, int lda, double[] work); + public abstract double execute(char norm, int m, int n, double[] a, int lda, double[] work); + + public static DlangeNode create() { + return RFFIFactory.getRFFI().getLapackRFFI().createDlangeNode(); + } + } + + abstract class DgeconNode extends Node { /** * See <a href="http://www.netlib.org/lapack/explore-html/db/de4/dgecon_8f.html">spec</a>. */ - public abstract int dgecon(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork); + public abstract int execute(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork); + + public static DgeconNode create() { + return RFFIFactory.getRFFI().getLapackRFFI().createDgeconNode(); + } + } - public abstract int dsyevr(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, double[] w, + abstract class DsyevrNode extends Node { + + public abstract int execute(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, double[] w, double[] z, int ldz, int[] isuppz, double[] work, int lwork, int[] iwork, int liwork); + + public static DsyevrNode create() { + return RFFIFactory.getRFFI().getLapackRFFI().createDsyevrNode(); + } } - LapackRFFINode createLapackRFFINode(); + IlaverNode createIlaverNode(); + + DgeevNode createDgeevNode(); + + Dgeqp3Node createDgeqp3Node(); + + DormqrNode createDormqrNode(); + + DtrtrsNode createDtrtrsNode(); + + DgetrfNode createDgetrfNode(); + + DpotrfNode createDpotrfNode(); + + DpotriNode createDpotriNode(); + + DpstrfNode createDpstrfNode(); + + DgesvNode createDgesvNode(); + + DlangeNode createDlangeNode(); + + DgeconNode createDgeconNode(); + + DsyevrNode createDsyevrNode(); + } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/MiscRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/MiscRFFI.java index 28ad96a3b65095f9363cfab470a76e9078a8a576..a401f6b1b84c35c807d0f3051392adfbb77692e4 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/MiscRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/MiscRFFI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,11 +22,21 @@ */ package com.oracle.truffle.r.runtime.ffi; +import com.oracle.truffle.api.nodes.Node; + /** * Miscellaneous methods implemented in native code. * */ public interface MiscRFFI { - double exactSum(double[] values, boolean hasNa, boolean naRm); + abstract class ExactSumNode extends Node { + public abstract double execute(double[] values, boolean hasNa, boolean naRm); + + public static ExactSumNode create() { + return RFFIFactory.getRFFI().getMiscRFFI().createExactSumNode(); + } + } + + ExactSumNode createExactSumNode(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RApplRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RApplRFFI.java index 189f88165c856c4296e52f25bdb2be52f43ec268..a8e4d2aa6dfb3ca4e740913ef8b28a1fad4b152e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RApplRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RApplRFFI.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 @@ -30,15 +30,34 @@ import com.oracle.truffle.api.nodes.Node; * {@code libappl} library in GnuR. */ public interface RApplRFFI { - abstract class RApplRFFINode extends Node { - // Linpack - public abstract void dqrdc2(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work); + abstract class Dqrdc2Node extends Node { + public abstract void execute(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work); - public abstract void dqrcf(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info); + public static Dqrdc2Node create() { + return RFFIFactory.getRFFI().getRApplRFFI().createDqrdc2Node(); + } + } + + abstract class DqrcfNode extends Node { + public abstract void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info); - public abstract void dqrls(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work); + public static Dqrdc2Node create() { + return RFFIFactory.getRFFI().getRApplRFFI().createDqrdc2Node(); + } } - RApplRFFINode createRApplRFFINode(); + abstract class DqrlsNode extends Node { + public abstract void execute(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work); + + public static DqrlsNode create() { + return RFFIFactory.getRFFI().getRApplRFFI().createDqrlsNode(); + } + } + + Dqrdc2Node createDqrdc2Node(); + + DqrcfNode createDqrcfNode(); + + DqrlsNode createDqrlsNode(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.java index ccc6224ba183630e07ad2a4ca7dce1ccb2c14766..12c23e7e6db57193e08ae842b1559bfe94e3a517 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.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 @@ -61,8 +61,6 @@ public interface RFFI { ToolsRFFI getToolsRFFI(); - GridRFFI getGridRFFI(); - CRFFI getCRFFI(); CallRFFI getCallRFFI(); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFICstring.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFICstring.java index c8dbee39e12f83ea246b81d120268560bb150ae7..5d50ed6f2cca867aa9ec80826bf7746e350cf17c 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFICstring.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFICstring.java @@ -28,10 +28,11 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Tags an upcall argument as being (on the native side) a C string. + * Tags an upcall argument as being (on the native side) a C string. By default the C string is + * converted to a {@link String}, which requires it to be null-terminated. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface RFFICstring { - + boolean convert() default true; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java index 35fdd63dac7b346cfd6cdcb1f1b73c76c890b90c..60d3811bdbcefdcc5734b1e99cc5d6defc588114 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java @@ -23,6 +23,7 @@ package com.oracle.truffle.r.runtime.ffi; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.r.runtime.FastRConfig; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.context.RContext.ContextState; @@ -30,11 +31,30 @@ import com.oracle.truffle.r.runtime.context.RContext.ContextState; * Factory class for the different possible implementations of the {@link RFFI} interface. * * The RFFI may need to do special things in the case of multiple contexts, hence any given factory - * must support the {@link #newContextState()} method. + * must support the {@link #newContextState()} method. Initialization of factory state that is + * dependent on the system being properly initialized <b>must</b> be done in the + * {@link ContextState#initialize} method and not in the constructor or {@link #createRFFI} method + * as they are invoked in the static block and the system is not typically initialized at that + * point. */ public abstract class RFFIFactory { - private static final String FACTORY_CLASS_PROPERTY = "fastr.ffi.factory.class"; - private static final String DEFAULT_FACTORY_CLASS = "com.oracle.truffle.r.runtime.ffi.jni.JNI_RFFIFactory"; + private enum Factory { + JNI("com.oracle.truffle.r.runtime.ffi.jni.JNI_RFFIFactory"), + LLVM("com.oracle.truffle.r.engine.interop.ffi.llvm.TruffleLLVM_RFFIFactory"), + MANAGED("com.oracle.truffle.r.runtime.ffi.managed.Managed_RFFIFactory"), + NFI("com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_RFFIFactory"); + + private final String klassName; + + Factory(String klassName) { + this.klassName = klassName; + } + } + + private static final String FACTORY_CLASS_PROPERTY = "fastr.rffi.factory.class"; + private static final String FACTORY_CLASS_NAME_PROPERTY = "fastr.rffi.factory"; + private static final String FACTORY_CLASS_ENV = "FASTR_RFFI"; + private static final Factory DEFAULT_FACTORY = Factory.JNI; /** * Singleton instance of the factory. @@ -43,20 +63,45 @@ public abstract class RFFIFactory { @CompilationFinal protected static RFFI theRFFI; - public static RFFIFactory initialize() { + static { if (instance == null) { - String prop = System.getProperty(FACTORY_CLASS_PROPERTY); + String klassName = getFactoryClassName(); try { - if (prop == null) { - prop = DEFAULT_FACTORY_CLASS; - } - instance = (RFFIFactory) Class.forName(prop).newInstance(); + instance = (RFFIFactory) Class.forName(klassName).newInstance(); theRFFI = instance.createRFFI(); } catch (Exception ex) { - throw Utils.rSuicide("Failed to instantiate class: " + prop + ": " + ex); + throw Utils.rSuicide("Failed to instantiate class: " + klassName + ": " + ex); } } - return instance; + } + + private static String getFactoryClassName() { + String prop = System.getProperty(FACTORY_CLASS_PROPERTY); + if (prop != null) { + return prop; + } + prop = System.getProperty(FACTORY_CLASS_NAME_PROPERTY); + if (prop != null) { + return checkFactoryName(prop); + } + prop = System.getenv(FACTORY_CLASS_ENV); + if (prop != null) { + return checkFactoryName(prop); + } + if (FastRConfig.ManagedMode) { + return Factory.MANAGED.klassName; + } + return DEFAULT_FACTORY.klassName; + } + + private static String checkFactoryName(String prop) { + try { + Factory factory = Factory.valueOf(prop.toUpperCase()); + return factory.klassName; + } catch (IllegalArgumentException ex) { + throw Utils.rSuicide("No RFFI factory: " + prop); + } + } public static RFFIFactory getInstance() { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIRootNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIRootNode.java index 71d8f98278e42b662db1ed71c61af3c27d70ff00..d6b8451a812102fa1304ee76503492aad10c0fc0 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIRootNode.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIRootNode.java @@ -31,6 +31,7 @@ import com.oracle.truffle.r.runtime.context.RContext; public abstract class RFFIRootNode<T extends Node> extends RootNode { @Child T rffiNode; + @SuppressWarnings("deprecation") protected RFFIRootNode(T baseRFFINode) { super(RContext.getRRuntimeASTAccess().getTruffleRLanguage(), null, new FrameDescriptor()); this.rffiNode = baseRFFINode; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java index 3d96124a1cae1cfce8e8af31608e92dd60bbc9a6..295eaa8c02ee461e643a0532a8707a46c4db8fd1 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java @@ -65,7 +65,7 @@ public interface StdUpCallsRFFI { Object Rf_coerceVector(Object x, int mode); - Object Rf_mkCharLenCE(@RFFICstring Object bytes, int len, int encoding); + Object Rf_mkCharLenCE(@RFFICstring(convert = false) Object bytes, int len, int encoding); Object Rf_cons(Object car, Object cdr); @@ -73,6 +73,8 @@ public interface StdUpCallsRFFI { Object R_do_MAKE_CLASS(@RFFICstring Object clazz); + Object R_do_new_object(Object classDef); + /** * WARNING: argument order reversed from Rf_findVarInFrame! */ @@ -90,6 +92,8 @@ public interface StdUpCallsRFFI { Object Rf_install(@RFFICstring Object name); + Object Rf_installChar(Object name); + Object Rf_lengthgets(Object x, int newSize); int Rf_isString(Object x); @@ -104,11 +108,11 @@ public interface StdUpCallsRFFI { void Rf_warningcall(Object call, @RFFICstring Object msg); - Object Rf_allocateVector(int mode, int n); + Object Rf_allocVector(int mode, int n); - Object Rf_allocateArray(int mode, Object dimsObj); + Object Rf_allocArray(int mode, Object dimsObj); - Object Rf_allocateMatrix(int mode, int nrow, int ncol); + Object Rf_allocMatrix(int mode, int nrow, int ncol); int Rf_nrows(Object x); @@ -142,7 +146,7 @@ public interface StdUpCallsRFFI { Object Rf_duplicate(Object x, int deep); - int Rf_anyDuplicated(Object x, int fromLast); + int Rf_any_duplicated(Object x, int fromLast); Object PRINTNAME(Object x); @@ -176,7 +180,7 @@ public interface StdUpCallsRFFI { Object Rf_eval(Object expr, Object env); - Object Rf_findfun(Object symbolObj, Object envObj); + Object Rf_findFun(Object symbolObj, Object envObj); Object Rf_GetOption1(Object tag); @@ -184,7 +188,7 @@ public interface StdUpCallsRFFI { void DUPLICATE_ATTRIB(Object to, Object from); - int R_computeIdentical(Object x, Object y, int flags); + int R_compute_identical(Object x, Object y, int flags); void Rf_copyListMatrix(Object s, Object t, int byrow); @@ -214,6 +218,10 @@ public interface StdUpCallsRFFI { int IS_S4_OBJECT(Object x); + void SET_S4_OBJECT(Object x); + + void UNSET_S4_OBJECT(Object x); + void Rprintf(@RFFICstring Object message); void GetRNGstate(); @@ -230,17 +238,17 @@ public interface StdUpCallsRFFI { Object R_ExternalPtrTag(Object x); - Object R_ExternalPtrProt(Object x); + Object R_ExternalPtrProtected(Object x); void R_SetExternalPtrAddr(Object x, long addr); void R_SetExternalPtrTag(Object x, Object tag); - void R_SetExternalPtrProt(Object x, Object prot); + void R_SetExternalPtrProtected(Object x, Object prot); void R_CleanUp(int sa, int status, int runlast); - REnvironment R_NewHashedEnv(REnvironment parent, int initialSize); + REnvironment R_NewHashedEnv(REnvironment parent, Object initialSize); int PRSEEN(Object x); @@ -252,4 +260,26 @@ public interface StdUpCallsRFFI { Object R_CHAR(Object x); + Object R_new_custom_connection(@RFFICstring Object description, @RFFICstring Object mode, @RFFICstring Object className, Object readAddr); + + int R_ReadConnection(int fd, byte[] buf); + + int R_WriteConnection(int fd, byte[] buf); + + Object R_GetConnection(int fd); + + String getSummaryDescription(Object x); + + String getConnectionClassString(Object x); + + String getOpenModeString(Object x); + + boolean isSeekable(Object x); + + Object R_do_slot(Object o, Object name); + + Object R_do_slot_assign(Object o, Object name, Object value); + + Object R_MethodsNamespace(); + } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToDoubleVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/FilesystemUtils.java similarity index 57% rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToDoubleVectorClosure.java rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/FilesystemUtils.java index 6d03d530fe73b7cb7579a45d3069ce6f1e5fdaa2..ea6d2db107390757d02ebe5e82e258cab7a487f0 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToDoubleVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/FilesystemUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,20 +20,22 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.data.closures; +package com.oracle.truffle.r.runtime.ffi.managed; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; +import java.nio.file.attribute.PosixFilePermission; +import java.util.EnumSet; +import java.util.Set; -final class RRawToDoubleVectorClosure extends RToDoubleVectorClosure implements RAbstractDoubleVector { +class FilesystemUtils { + private static PosixFilePermission[] permissionValues = PosixFilePermission.values(); - RRawToDoubleVectorClosure(RAbstractRawVector vector) { - super(vector); - } - - @Override - public double getDataAt(int index) { - return RRuntime.raw2double(((RAbstractRawVector) vector).getDataAt(index)); + static Set<PosixFilePermission> permissionsFromMode(int mode) { + Set<PosixFilePermission> permissions = EnumSet.noneOf(PosixFilePermission.class); + for (int i = 0; i < permissionValues.length; i++) { + if ((mode & (1 << (permissionValues.length - i - 1))) != 0) { + permissions.add(permissionValues[i]); + } + } + return permissions; } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_Base.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_Base.java new file mode 100644 index 0000000000000000000000000000000000000000..988632777ab42c6b239cdbc8abcaa70a1c96119f --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_Base.java @@ -0,0 +1,185 @@ +/* + * 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.runtime.ffi.managed; + +import static com.oracle.truffle.r.runtime.ffi.managed.FilesystemUtils.permissionsFromMode; +import static com.oracle.truffle.r.runtime.ffi.managed.Managed_RFFIFactory.unsupported; + +import java.io.IOException; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; +import java.util.Set; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.ffi.BaseRFFI; + +public class Managed_Base implements BaseRFFI { + /** + * Process id is used as seed for random number generator. We return another "random" number. + */ + @Override + public GetpidNode createGetpidNode() { + return new GetpidNode() { + private int fakePid = (int) System.currentTimeMillis(); + + @Override + public int execute() { + return fakePid; + } + }; + } + + @Override + public GetwdNode createGetwdNode() { + return new GetwdNode() { + @Override + @TruffleBoundary + public String execute() { + return Paths.get(".").toAbsolutePath().normalize().toString(); + } + }; + } + + @Override + public SetwdNode createSetwdNode() { + return new SetwdNode() { + @Override + public int execute(String dir) { + throw unsupported("setwd"); + } + }; + } + + @Override + public MkdirNode createMkdirNode() { + return new MkdirNode() { + @Override + @TruffleBoundary + public void execute(String dir, int mode) throws IOException { + Set<PosixFilePermission> permissions = permissionsFromMode(mode); + Files.createDirectories(Paths.get(dir), PosixFilePermissions.asFileAttribute(permissions)); + } + }; + } + + @Override + public ReadlinkNode createReadlinkNode() { + return new ReadlinkNode() { + @Override + public String execute(String path) throws IOException { + throw unsupported("linknode"); + } + }; + } + + @Override + public MkdtempNode createMkdtempNode() { + return new MkdtempNode() { + @Override + @TruffleBoundary + public String execute(String template) { + Path path = null; + boolean done = false; + while (!done) { + try { + path = Paths.get(template); + Files.createDirectories(path); + done = true; + } catch (FileAlreadyExistsException e) { + // nop + } catch (IOException e) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Cannot create temp directories."); + } + } + return path.toString(); + } + }; + } + + @Override + public ChmodNode createChmodNode() { + return new ChmodNode() { + @Override + @TruffleBoundary + public int execute(String path, int mode) { + try { + Files.setPosixFilePermissions(Paths.get(path), permissionsFromMode(mode)); + return mode; + } catch (IOException e) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, "Cannot change file permissions."); + } + } + }; + } + + @Override + public StrolNode createStrolNode() { + return null; + } + + @Override + public UnameNode createUnameNode() { + return new UnameNode() { + @Override + public UtsName execute() { + return new UtsName() { + @Override + public String sysname() { + return System.getProperty("os.name"); + } + + @Override + public String release() { + return ""; + } + + @Override + public String version() { + return System.getProperty("os.version"); + } + + @Override + public String machine() { + return System.getProperty("os.arch"); + } + + @Override + public String nodename() { + return ""; + } + }; + } + }; + } + + @Override + public GlobNode createGlobNode() { + return null; + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_LapackRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_LapackRFFI.java new file mode 100644 index 0000000000000000000000000000000000000000..2b532244fe888586a9194c3d15a61281f6b4c56c --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_LapackRFFI.java @@ -0,0 +1,94 @@ +/* + * 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.runtime.ffi.managed; + +import static com.oracle.truffle.r.runtime.ffi.managed.Managed_RFFIFactory.unsupported; + +import com.oracle.truffle.r.runtime.ffi.LapackRFFI; + +public class Managed_LapackRFFI implements LapackRFFI { + @Override + public IlaverNode createIlaverNode() { + throw unsupported("lapack"); + } + + @Override + public DgeevNode createDgeevNode() { + throw unsupported("lapack"); + } + + @Override + public Dgeqp3Node createDgeqp3Node() { + throw unsupported("lapack"); + } + + @Override + public DormqrNode createDormqrNode() { + throw unsupported("lapack"); + } + + @Override + public DtrtrsNode createDtrtrsNode() { + throw unsupported("lapack"); + } + + @Override + public DgetrfNode createDgetrfNode() { + throw unsupported("lapack"); + } + + @Override + public DpotrfNode createDpotrfNode() { + throw unsupported("lapack"); + } + + @Override + public DpotriNode createDpotriNode() { + throw unsupported("lapack"); + } + + @Override + public DpstrfNode createDpstrfNode() { + throw unsupported("lapack"); + } + + @Override + public DgesvNode createDgesvNode() { + throw unsupported("lapack"); + } + + @Override + public DlangeNode createDlangeNode() { + throw unsupported("lapack"); + } + + @Override + public DgeconNode createDgeconNode() { + throw unsupported("lapack"); + } + + @Override + public DsyevrNode createDsyevrNode() { + throw unsupported("lapack"); + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_PCRERFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_PCRERFFI.java new file mode 100644 index 0000000000000000000000000000000000000000..622b78cc0cdd864ca1bb89675b6b7b85f6c2a8df --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_PCRERFFI.java @@ -0,0 +1,59 @@ +/* + * 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.runtime.ffi.managed; + +import static com.oracle.truffle.r.runtime.ffi.managed.Managed_RFFIFactory.unsupported; + +import com.oracle.truffle.r.runtime.ffi.PCRERFFI; + +public class Managed_PCRERFFI implements PCRERFFI { + @Override + public MaketablesNode createMaketablesNode() { + throw unsupported("PCRE"); + } + + @Override + public CompileNode createCompileNode() { + throw unsupported("PCRE"); + } + + @Override + public GetCaptureCountNode createGetCaptureCountNode() { + throw unsupported("PCRE"); + } + + @Override + public GetCaptureNamesNode createGetCaptureNamesNode() { + throw unsupported("PCRE"); + } + + @Override + public StudyNode createStudyNode() { + throw unsupported("PCRE"); + } + + @Override + public ExecNode createExecNode() { + throw unsupported("PCRE"); + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToComplexVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_REmbedRFFI.java similarity index 55% rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToComplexVectorClosure.java rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_REmbedRFFI.java index b699420159a5afbd62fd24bf766ffffc5a171507..9d0a0a079fe7efb08d4405daf6eb71fa88c85f7a 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToComplexVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_REmbedRFFI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,24 +20,35 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.data.closures; +package com.oracle.truffle.r.runtime.ffi.managed; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; +import static com.oracle.truffle.r.runtime.ffi.managed.Managed_RFFIFactory.unsupported; -final class RRawToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector { +import com.oracle.truffle.r.runtime.ffi.REmbedRFFI; - private final RAbstractRawVector logicalVector; +public class Managed_REmbedRFFI implements REmbedRFFI { + @Override + public void suicide(String x) { + throw unsupported("REmbed"); + } + + @Override + public void cleanUp(int type, int x, int y) { + throw unsupported("REmbed"); + } - RRawToComplexVectorClosure(RAbstractRawVector vector) { - super(vector); - this.logicalVector = vector; + @Override + public String readConsole(String prompt) { + throw unsupported("REmbed"); + } + + @Override + public void writeConsole(String x) { + throw unsupported("REmbed"); } @Override - public RComplex getDataAt(int index) { - return RRuntime.raw2complex(logicalVector.getDataAt(index)); + public void writeErrConsole(String x) { + throw unsupported("REmbed"); } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_RFFIFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_RFFIFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..36a30ba75a0f91ad6cfd0cfe9b4d2267bb454782 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_RFFIFactory.java @@ -0,0 +1,215 @@ +/* + * 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.runtime.ffi.managed; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.context.RContext.ContextState; +import com.oracle.truffle.r.runtime.ffi.BaseRFFI; +import com.oracle.truffle.r.runtime.ffi.CRFFI; +import com.oracle.truffle.r.runtime.ffi.CallRFFI; +import com.oracle.truffle.r.runtime.ffi.DLLRFFI; +import com.oracle.truffle.r.runtime.ffi.LapackRFFI; +import com.oracle.truffle.r.runtime.ffi.MiscRFFI; +import com.oracle.truffle.r.runtime.ffi.PCRERFFI; +import com.oracle.truffle.r.runtime.ffi.RApplRFFI; +import com.oracle.truffle.r.runtime.ffi.REmbedRFFI; +import com.oracle.truffle.r.runtime.ffi.RFFI; +import com.oracle.truffle.r.runtime.ffi.RFFIFactory; +import com.oracle.truffle.r.runtime.ffi.StatsRFFI; +import com.oracle.truffle.r.runtime.ffi.ToolsRFFI; +import com.oracle.truffle.r.runtime.ffi.UserRngRFFI; +import com.oracle.truffle.r.runtime.ffi.ZipRFFI; + +/** + * Operations that can be, at least partially, implemented in Java are implemented, other operations + * throw {@link RError}. + */ +public class Managed_RFFIFactory extends RFFIFactory implements RFFI { + @Override + protected RFFI createRFFI() { + return this; + } + + @Override + public BaseRFFI getBaseRFFI() { + return new Managed_Base(); + } + + @Override + public LapackRFFI getLapackRFFI() { + return new Managed_LapackRFFI(); + } + + @Override + public RApplRFFI getRApplRFFI() { + return new RApplRFFI() { + @Override + public Dqrdc2Node createDqrdc2Node() { + throw unsupported("dqrdc"); + } + + @Override + public DqrcfNode createDqrcfNode() { + throw unsupported("dqrcf"); + } + + @Override + public DqrlsNode createDqrlsNode() { + throw unsupported("dqrls"); + } + }; + } + + @Override + public StatsRFFI getStatsRFFI() { + return new StatsRFFI() { + @Override + public FactorNode createFactorNode() { + throw unsupported("factor"); + } + + @Override + public WorkNode createWorkNode() { + throw unsupported("work"); + } + }; + } + + @Override + public ToolsRFFI getToolsRFFI() { + return new ToolsRFFI() { + @Override + public ParseRdNode createParseRdNode() { + throw unsupported("parseRD"); + } + }; + } + + @Override + public CRFFI getCRFFI() { + return new CRFFI() { + @Override + public InvokeCNode createInvokeCNode() { + throw unsupported("invoke"); + } + }; + } + + @Override + public CallRFFI getCallRFFI() { + return new CallRFFI() { + @Override + public InvokeCallNode createInvokeCallNode() { + throw unsupported("native code invocation"); + } + + @Override + public InvokeVoidCallNode createInvokeVoidCallNode() { + throw unsupported("native code invocation"); + } + }; + } + + @Override + public UserRngRFFI getUserRngRFFI() { + return new UserRngRFFI() { + @Override + public UserRngRFFINode createUserRngRFFINode() { + throw unsupported("user defined RNG"); + } + }; + } + + @Override + public PCRERFFI getPCRERFFI() { + return new Managed_PCRERFFI(); + } + + @Override + public ZipRFFI getZipRFFI() { + return new ZipRFFI() { + @Override + public CompressNode createCompressNode() { + throw unsupported("zip compression"); + } + + @Override + public UncompressNode createUncompressNode() { + throw unsupported("zip decompression"); + } + }; + } + + @Override + public DLLRFFI getDLLRFFI() { + return new DLLRFFI() { + @Override + public DLOpenNode createDLOpenNode() { + throw unsupported("DLL open"); + } + + @Override + public DLSymNode createDLSymNode() { + throw unsupported("createDLSym"); + } + + @Override + public DLCloseNode createDLCloseNode() { + throw unsupported("createDLClose"); + } + }; + } + + @Override + public REmbedRFFI getREmbedRFFI() { + return new Managed_REmbedRFFI(); + } + + @Override + public MiscRFFI getMiscRFFI() { + return new MiscRFFI() { + @Override + public ExactSumNode createExactSumNode() { + throw unsupported("exactsum"); + } + }; + } + + @Override + public ContextState newContextState() { + return new ContextState() { + @Override + public ContextState initialize(RContext context) { + return this; + } + }; + } + + @TruffleBoundary + static RError unsupported(String name) { + throw RError.error(RError.NO_CALLER, Message.GENERIC, String.format("Feature '%s' is not supported by managed FFI, i.e. it requires running native code.", name)); + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java index 4740bd9bc7c7364e73f758441c9621f7c8a45a30..9aa6e79d3426372eac3b29810ce4fb1e4b684449 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java @@ -14,9 +14,7 @@ package com.oracle.truffle.r.runtime.gnur; import java.util.HashMap; import java.util.Map; -import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.conn.RConnection; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RComplexVector; @@ -48,18 +46,6 @@ import com.oracle.truffle.r.runtime.env.REnvironment; public enum SEXPTYPE { - /* - * FastR scalar variants of GnuR vector types (other than String) These could be removed in a - * similar way to String, but there is no pressing need. - */ - FASTR_DOUBLE(300, Double.class), - FASTR_INT(301, Integer.class), - FASTR_BYTE(302, Byte.class), - FASTR_COMPLEX(303, RComplex.class), - // very special case - FASTR_SOURCESECTION(306, SourceSection.class), - FASTR_CONNECTION(307, RConnection.class), - NILSXP(0, RNull.class), /* nil ()NULL */ SYMSXP(1, RSymbol.class), /* symbols */ LISTSXP(2, RPairList.class), /* lists of dotted pairs */ @@ -70,10 +56,10 @@ public enum SEXPTYPE { SPECIALSXP(7), /* special forms */ BUILTINSXP(8), /* builtin non-special forms */ CHARSXP(9), /* "scalar" string type (GnuR internal only) */ - LGLSXP(10, RLogicalVector.class), /* logical vectors */ - INTSXP(13, RIntVector.class, RIntSequence.class), /* integer vectors */ - REALSXP(14, RDoubleVector.class, RDoubleSequence.class), /* real variables */ - CPLXSXP(15, RComplexVector.class), /* complex variables */ + LGLSXP(10, RLogicalVector.class, Byte.class), /* logical vectors */ + INTSXP(13, RIntVector.class, RIntSequence.class, Integer.class), /* integer vectors */ + REALSXP(14, RDoubleVector.class, RDoubleSequence.class, Double.class), /* real variables */ + CPLXSXP(15, RComplexVector.class, RComplex.class), /* complex variables */ STRSXP(16, RStringVector.class, String.class), /* string vectors */ DOTSXP(17, RArgsValuesAndNames.class), /* dot-dot-dot object */ ANYSXP(18), /* make "any" args work */ @@ -142,11 +128,9 @@ public enum SEXPTYPE { } } } - // (only) promises, environments and connections have subtypes + // (only) promises and environments have subtypes if (REnvironment.class.isAssignableFrom(fastRClass)) { return ENVSXP; - } else if (RConnection.class.isAssignableFrom(fastRClass)) { - return FASTR_CONNECTION; } else if (RPromise.class.isAssignableFrom(fastRClass)) { return PROMSXP; } @@ -174,52 +158,22 @@ public enum SEXPTYPE { */ public static SEXPTYPE gnuRType(SEXPTYPE type, Object obj) { switch (type) { - case FUNSXP: { + case FUNSXP: RFunction func = (RFunction) obj; if (func.isBuiltin()) { return SEXPTYPE.BUILTINSXP; } else { return SEXPTYPE.CLOSXP; } - } - - case LISTSXP: { + case LISTSXP: RPairList pl = (RPairList) obj; if (pl.getType() != null && pl.getType() == SEXPTYPE.LANGSXP) { return SEXPTYPE.LANGSXP; } else { return type; } - } - - case FASTR_INT: - return SEXPTYPE.INTSXP; - case FASTR_DOUBLE: - return SEXPTYPE.REALSXP; - case FASTR_BYTE: - return SEXPTYPE.LGLSXP; - case FASTR_COMPLEX: - return SEXPTYPE.CPLXSXP; - case FASTR_CONNECTION: - return SEXPTYPE.INTSXP; default: return type; } } - - public static SEXPTYPE convertFastRScalarType(SEXPTYPE type) { - switch (type) { - case FASTR_DOUBLE: - return SEXPTYPE.REALSXP; - case FASTR_INT: - return SEXPTYPE.INTSXP; - case FASTR_BYTE: - return SEXPTYPE.LGLSXP; - case FASTR_COMPLEX: - return SEXPTYPE.CPLXSXP; - default: - assert false; - return null; - } - } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/GammaFunctions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/GammaFunctions.java index 38a90070f967b34cf55c8ebb326ffa52cd895289..8979aeef7d4f1bc349c82ddfd74733af7223f8c3 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/GammaFunctions.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/GammaFunctions.java @@ -126,7 +126,7 @@ public abstract class GammaFunctions { private static final double M_LN_SQRT_2PI = 0.918938533204672741780329736406; - static double gammafn(double x) { + public static double gammafn(double x) { int i; int n; double y; @@ -1052,7 +1052,7 @@ public abstract class GammaFunctions { } f = res12 / elfb; - np = new Pnorm().evaluate(s2pt, 0.0, 1.0, !lowerTail, logp); + np = Pnorm.createTemp().evaluate(s2pt, 0.0, 1.0, !lowerTail, logp); if (logp) { double ndOverP = dpnorm(s2pt, !lowerTail, np); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RandomFunctions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RandomFunctions.java index 815481e6f4e32b83532e84615a8ebf485dd4b6e2..736cf4b3bd9700ea33d24061aa050f83024a7b2b 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RandomFunctions.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RandomFunctions.java @@ -22,9 +22,9 @@ */ package com.oracle.truffle.r.runtime.nmath; -import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.r.runtime.nmath.distr.SExp; import com.oracle.truffle.r.runtime.nmath.distr.SNorm; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.rng.RRNG; import com.oracle.truffle.r.runtime.rng.RRNG.NormKind; import com.oracle.truffle.r.runtime.rng.RandomNumberGenerator; @@ -34,7 +34,7 @@ import com.oracle.truffle.r.runtime.rng.RandomNumberGenerator; * implement common code for the vectorized versions. */ public class RandomFunctions { - public abstract static class RandFunction3_Double extends Node { + public abstract static class RandFunction3_Double extends RBaseNode { public abstract double execute(double a, double b, double c, RandomNumberProvider rand); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnorm.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnorm.java index bf069e9a0186908a05efc768ac27b87da679fbb7..4bb9d06fc8ba6608cccc0629ecfae3fc23894608 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnorm.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnorm.java @@ -22,7 +22,22 @@ import com.oracle.truffle.r.runtime.nmath.MathFunctions.Function3_2; public final class Pnorm implements Function3_2 { - private final BranchProfile nanProfile = BranchProfile.create(); + private final BranchProfile nanProfile; + + public Pnorm() { + this(BranchProfile.create()); + } + + private Pnorm(BranchProfile nanProfile) { + this.nanProfile = nanProfile; + } + + /** + * For use in a temporary (non-Truffle Node) context. + */ + public static Pnorm createTemp() { + return new Pnorm(null); + } @Override public double evaluate(double x, double mu, double sigma, boolean lowerTail, boolean logP) { @@ -31,7 +46,9 @@ public final class Pnorm implements Function3_2 { * == mu and sigma == 0, we get the correct answer 1. */ if (Double.isNaN(x) || Double.isNaN(mu) || Double.isNaN(sigma)) { - nanProfile.enter(); + if (nanProfile != null) { + nanProfile.enter(); + } return x + mu + sigma; } if (!Double.isFinite(x) && mu == x) { @@ -40,7 +57,9 @@ public final class Pnorm implements Function3_2 { } if (sigma <= 0) { if (sigma < 0) { - nanProfile.enter(); + if (nanProfile != null) { + nanProfile.enter(); + } return Double.NaN; } /* sigma = 0 : */ @@ -170,24 +189,24 @@ public final class Pnorm implements Function3_2 { /* * else |x| > sqrt(32) = 5.657 : the next two case differentiations were really for * lower=T, log=F Particularly *not* for log_p ! - * + * * Cody had (-37.5193 < x && x < 8.2924) ; R originally had y < 50 - * + * * Note that we do want symmetry(0), lower/upper -> hence use y */ } else if ((logP && y < 1e170) /* avoid underflow below */ /* * ^^^^^ MM FIXME: can speedup for log_p and much larger |x| ! Then, make use of * Abramowitz & Stegun, 26.2.13, something like - * + * * xsq = x*x; - * + * * if(xsq * DBL_EPSILON < 1.) del = (1. - (1. - 5./(xsq+6.)) / (xsq+4.)) / (xsq+2.); * else del = 0.;cum = -.5*xsq - M_LN_SQRT_2PI - log(x) + log1p(-del);ccum = * log1p(-exp(*cum)); /.* ~ log(1) = 0 *./ - * + * * swap_tail; - * + * * [Yes, but xsq might be infinite.] */ || (lower && -37.5193 < x && x < 8.2924) || (upper && -8.2924 < x && x < 37.5193)) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RHyper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RHyper.java index 2b501eb81df257876159fbbc7acdda78058cd656..3521424f9328756eee209e3d4869adcc3341e32a 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RHyper.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RHyper.java @@ -235,7 +235,7 @@ public final class RHyper extends RandFunction3_Double { v = rand.unifRand(); nUv++; if (nUv >= 10000) { - RError.warning(RError.SHOW_CALLER, Message.GENERIC, String.format("rhyper() branch III: giving up after %d rejections", nUv)); + warning(Message.GENERIC, String.format("rhyper() branch III: giving up after %d rejections", nUv)); return RMathError.defaultError(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SNorm.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SNorm.java index d818315b6d5ed4b6d3cee756b2368aec1721a862..7549bbc4924ea6a7b4401d9d53bca33fb6c39555 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SNorm.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SNorm.java @@ -11,31 +11,348 @@ */ package com.oracle.truffle.r.runtime.nmath.distr; -import com.oracle.truffle.r.runtime.RError; +import static java.lang.Math.cos; +import static java.lang.Math.exp; +import static java.lang.Math.log; +import static java.lang.Math.sin; +import static java.lang.Math.sqrt; +import static com.oracle.truffle.r.runtime.nmath.MathConstants.DBL_MIN; +import static com.oracle.truffle.r.runtime.nmath.MathConstants.M_PI; +import static com.oracle.truffle.r.runtime.nmath.TOMS708.fabs; +import static com.oracle.truffle.r.runtime.nmath.RMath.fmin2; +import static com.oracle.truffle.r.runtime.nmath.RMath.fmax2; + +import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.rng.RRNG.NormKind; import com.oracle.truffle.r.runtime.rng.RandomNumberGenerator; /** * Generation of random value from standard normal distribution N(0,1). Corresponds to * {@code snorm.c} in GnuR. Some other distributions can be generated by transformations of N(0,1). - * This is meant as common functinality for those. + * This is meant as common functionality for those. */ public final class SNorm { + + /* + * REFERENCE + * + * Ahrens, J.H. and Dieter, U. Extensions of Forsythe's method for random sampling from the + * normal distribution. Math. Comput. 27, 927-937. + * + * The definitions of the constants a[k], d[k], t[k] and h[k] are according to the + * abovementioned article + */ + + private static final double[] a = new double[]{ + 0.0000000, 0.03917609, 0.07841241, 0.1177699, + 0.1573107, 0.19709910, 0.23720210, 0.2776904, + 0.3186394, 0.36012990, 0.40225010, 0.4450965, + 0.4887764, 0.53340970, 0.57913220, 0.6260990, + 0.6744898, 0.72451440, 0.77642180, 0.8305109, + 0.8871466, 0.94678180, 1.00999000, 1.0775160, + 1.1503490, 1.22985900, 1.31801100, 1.4177970, + 1.5341210, 1.67594000, 1.86273200, 2.1538750 + }; + + private static final double[] d = new double[]{ + 0.0000000, 0.0000000, 0.0000000, 0.0000000, + 0.0000000, 0.2636843, 0.2425085, 0.2255674, + 0.2116342, 0.1999243, 0.1899108, 0.1812252, + 0.1736014, 0.1668419, 0.1607967, 0.1553497, + 0.1504094, 0.1459026, 0.1417700, 0.1379632, + 0.1344418, 0.1311722, 0.1281260, 0.1252791, + 0.1226109, 0.1201036, 0.1177417, 0.1155119, + 0.1134023, 0.1114027, 0.1095039 + }; + + private static final double[] t = new double[]{ + 7.673828e-4, 0.002306870, 0.003860618, 0.005438454, + 0.007050699, 0.008708396, 0.010423570, 0.012209530, + 0.014081250, 0.016055790, 0.018152900, 0.020395730, + 0.022811770, 0.025434070, 0.028302960, 0.031468220, + 0.034992330, 0.038954830, 0.043458780, 0.048640350, + 0.054683340, 0.061842220, 0.070479830, 0.081131950, + 0.094624440, 0.112300100, 0.136498000, 0.171688600, + 0.227624100, 0.330498000, 0.584703100 + }; + + private static final double[] h = new double[]{ + 0.03920617, 0.03932705, 0.03950999, 0.03975703, + 0.04007093, 0.04045533, 0.04091481, 0.04145507, + 0.04208311, 0.04280748, 0.04363863, 0.04458932, + 0.04567523, 0.04691571, 0.04833487, 0.04996298, + 0.05183859, 0.05401138, 0.05654656, 0.05953130, + 0.06308489, 0.06737503, 0.07264544, 0.07926471, + 0.08781922, 0.09930398, 0.11555990, 0.14043440, + 0.18361420, 0.27900160, 0.70104740 + }; + + /*----------- Constants and definitions for Kinderman - Ramage --- */ + /* + * REFERENCE + * + * Kinderman A. J. and Ramage J. G. (1976). Computer generation of normal random variables. JASA + * 71, 893-896. + */ + + private static final double C1 = 0.398942280401433; + private static final double C2 = 0.180025191068563; + private static final double A = 2.216035867166471; + + private static double g(double x) { + return C1 * exp(-x * x / 2.0) - C2 * (A - x); + } + + private static final double BIG = 134217728; /* 2^27 */ + + static double BMNormKeep = 0.0; + private SNorm() { // only static members } - // TODO: implement other normKinds + public static double normRand(RandomNumberGenerator rand, NormKind normKind) { + double s; + double u1; + double w; + double y; + double u2; + double u3; + double aa; + double tt; + double theta; + double r; + int i; + + switch (normKind) { + case BUGGY_KINDERMAN_RAMAGE: /* see Reference above */ + /* + * note: this has problems, but is retained for reproducibility of older codes. + */ + /* unif_rand() alone is not of high enough precision */ + u1 = rand.genrandDouble(); + if (u1 < 0.884070402298758) { + u2 = rand.genrandDouble(); + return A * (1.13113163544180 * u1 + u2 - 1); + } - private static final double BIG = 134217728; /* 2^27 */ + if (u1 >= 0.973310954173898) { /* tail: */ + while (true) { + u2 = rand.genrandDouble(); + u3 = rand.genrandDouble(); + tt = (A * A - 2 * log(u3)); + if (u2 * u2 < (A * A) / tt) { + return (u1 < 0.986655477086949) ? sqrt(tt) : -sqrt(tt); + } + } + } - public static double normRand(RandomNumberGenerator rand, NormKind normKind) { - if (normKind != NormKind.INVERSION) { - throw RError.nyi(null, "unifNorm(): no other NormKind than the default INVERSION is implemented"); + if (u1 >= 0.958720824790463) { /* region3: */ + while (true) { + u2 = rand.genrandDouble(); + u3 = rand.genrandDouble(); + tt = A - 0.630834801921960 * fmin2(u2, u3); + if (fmax2(u2, u3) <= 0.755591531667601) { + return (u2 < u3) ? tt : -tt; + } + if (0.034240503750111 * fabs(u2 - u3) <= g(tt)) { + return (u2 < u3) ? tt : -tt; + } + } + } + + if (u1 >= 0.911312780288703) { /* region2: */ + while (true) { + u2 = rand.genrandDouble(); + u3 = rand.genrandDouble(); + tt = 0.479727404222441 + 1.105473661022070 * fmin2(u2, u3); + if (fmax2(u2, u3) <= 0.872834976671790) { + return (u2 < u3) ? tt : -tt; + } + if (0.049264496373128 * fabs(u2 - u3) <= g(tt)) { + return (u2 < u3) ? tt : -tt; + } + } + } + + /* ELSE region1: */ + if (true) { // Satisfy foolish style checker requiring "break" + // or "return" after infinite loops + while (true) { + u2 = rand.genrandDouble(); + u3 = rand.genrandDouble(); + tt = 0.479727404222441 - 0.595507138015940 * fmin2(u2, u3); + if (fmax2(u2, u3) <= 0.805577924423817) { + return (u2 < u3) ? tt : -tt; + } + } + } + return 0d; // can NEVER reach here (infinite loop ahead) + + case AHRENS_DIETER: + /* unif_rand() alone is not of high enough precision */ + u1 = rand.genrandDouble(); + s = 0.0; + if (u1 > 0.5) { + s = 1.0; + } + u1 = u1 + u1 - s; + u1 *= 32.0; + i = (int) u1; + if (i == 32) { + i = 31; + } + if (i != 0) { + u2 = u1 - i; + aa = a[i - 1]; + while (u2 <= t[i - 1]) { + u1 = rand.genrandDouble(); + w = u1 * (a[i] - aa); + tt = (w * 0.5 + aa) * w; + while (true) { + if (u2 > tt) { + // Original code: goto deliver; + // inlined the code after the label: + y = aa + w; + return (s == 1.0) ? -y : y; + } + u1 = rand.genrandDouble(); + if (u2 < u1) { + break; + } + tt = u1; + u2 = rand.genrandDouble(); + } + u2 = rand.genrandDouble(); + } + w = (u2 - t[i - 1]) * h[i - 1]; + } else { + i = 6; + aa = a[31]; + while (true) { + u1 = u1 + u1; + if (u1 >= 1.0) { + break; + } + aa = aa + d[i - 1]; + i = i + 1; + } + u1 = u1 - 1.0; + jump: while (true) { + w = u1 * d[i - 1]; + tt = (w * 0.5 + aa) * w; + while (true) { + u2 = rand.genrandDouble(); + if (u2 > tt) { + break jump; + } + u1 = rand.genrandDouble(); + if (u2 < u1) { + break; + } + tt = u1; + } + u1 = rand.genrandDouble(); + } + } + // deliver: + y = aa + w; + return (s == 1.0) ? -y : y; + + case BOX_MULLER: + if (BMNormKeep != 0.0) { /* An exact test is intentional */ + s = BMNormKeep; + BMNormKeep = 0.0; + return s; + } else { + theta = 2d * M_PI * rand.genrandDouble(); + r = sqrt(-2d * log(rand.genrandDouble())) + 10d * DBL_MIN; /* ensure non-zero */ + BMNormKeep = r * sin(theta); + return r * cos(theta); + } + + case USER_NORM: + // Not implemented yet. C impl: return *((double *) User_norm_fun()); + throw RInternalError.shouldNotReachHere(); + + case INVERSION: + /* unif_rand() alone is not of high enough precision */ + u1 = rand.genrandDouble(); + u1 = (int) (BIG * u1) + rand.genrandDouble(); + return Qnorm.qnorm(u1 / BIG, 0.0, 1.0, true, false); + + case KINDERMAN_RAMAGE: /* see Reference above */ + /* + * corrected version from Josef Leydold + */ + u1 = rand.genrandDouble(); + if (u1 < 0.884070402298758) { + u2 = rand.genrandDouble(); + return A * (1.131131635444180 * u1 + u2 - 1); + } + + if (u1 >= 0.973310954173898) { /* tail: */ + while (true) { + u2 = rand.genrandDouble(); + u3 = rand.genrandDouble(); + tt = (A * A - 2 * log(u3)); + if (u2 * u2 < (A * A) / tt) { + return (u1 < 0.986655477086949) ? sqrt(tt) : -sqrt(tt); + } + } + } + + if (u1 >= 0.958720824790463) { /* region3: */ + while (true) { + u2 = rand.genrandDouble(); + u3 = rand.genrandDouble(); + tt = A - 0.630834801921960 * fmin2(u2, u3); + if (fmax2(u2, u3) <= 0.755591531667601) { + return (u2 < u3) ? tt : -tt; + } + if (0.034240503750111 * fabs(u2 - u3) <= g(tt)) { + return (u2 < u3) ? tt : -tt; + } + } + } + + if (u1 >= 0.911312780288703) { /* region2: */ + while (true) { + u2 = rand.genrandDouble(); + u3 = rand.genrandDouble(); + tt = 0.479727404222441 + 1.105473661022070 * fmin2(u2, u3); + if (fmax2(u2, u3) <= 0.872834976671790) { + return (u2 < u3) ? tt : -tt; + } + if (0.049264496373128 * fabs(u2 - u3) <= g(tt)) { + return (u2 < u3) ? tt : -tt; + } + } + } + + /* ELSE region1: */ + if (true) { // Satisfy foolish style checker requiring "break" + // or "return" after infinite loops + while (true) { + u2 = rand.genrandDouble(); + u3 = rand.genrandDouble(); + tt = 0.479727404222441 - 0.595507138015940 * fmin2(u2, u3); + if (tt < 0.) { + continue; + } + if (fmax2(u2, u3) <= 0.805577924423817) { + return (u2 < u3) ? tt : -tt; + } + if (0.053377549506886 * fabs(u2 - u3) <= g(tt)) { + return (u2 < u3) ? tt : -tt; + } + } + } + return 0d; // can NEVER reach here (infinite loop ahead) + + default: + assert false; + return 0d; } - /* unif_rand() alone is not of high enough precision */ - double u1 = rand.genrandDouble(); - u1 = (int) (BIG * u1) + rand.genrandDouble(); - return Qnorm.qnorm(u1 / BIG, 0.0, 1.0, true, false); } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Signrank.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Signrank.java index 2d1baf7bbb09de6887be963fc120e934f6304e5c..18917863d2a0c1bfe2e89faa040b71bf7810dc22 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Signrank.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Signrank.java @@ -66,7 +66,7 @@ public final class Signrank { } private static RError couldNotAllocateError() { - return RError.error(RError.SHOW_CALLER, CALLOC_COULD_NOT_ALLOCATE, "18446744073172680704", 8); + throw RError.error(RError.SHOW_CALLER, CALLOC_COULD_NOT_ALLOCATE, "18446744073172680704", 8); } private static double csignrank(double[] w, int kIn, int n) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Wilcox.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Wilcox.java index fc9e1f2ecdac225c952861d95594006314befa11..eea537e0c6258a3f8654dab891c74e6aeb11e5c6 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Wilcox.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Wilcox.java @@ -100,7 +100,7 @@ public final class Wilcox { private static RError couldNotAllocateError() { // GnuR seems to be reporting the same number regardless of the actual size? - return RError.error(RError.SHOW_CALLER, CALLOC_COULD_NOT_ALLOCATE, "18446744071562067968", 4); + throw RError.error(RError.SHOW_CALLER, CALLOC_COULD_NOT_ALLOCATE, "18446744071562067968", 4); } private static double cwilcox(double[][][] w, int kIn, int m, int n) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java index b24242d83805613c6f717e4bf4d3ad420d401daf..99bed23f0f6583742e665a737cadaddb883f6125 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.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 @@ -77,8 +77,8 @@ final class Info { public final class EvaluatedArgumentsVisitor extends RSyntaxVisitor<Info> { private static final Set<String> wellKnownFunctions = new HashSet<>(Arrays.asList("c", "$", "@", "[", "[[", "any", "dim", "dimnames", "rownames", "colnames", "is.null", "list", "names", "return", - "print", "length", "rep", "min", "max", "matrix", "table", "is.array", "is.element", "is.character", "exp", "all", "pmin", "pmax", "as.numeric", "proc.time", "as.integer", - "as.character", "as.matrix", ".Call", "sum", "order", "rev", "integer", "double", "as.numeric", "as.list", "as.integer", ".Call", ".FastR", "unname", "log", "lgamma", + "print", "length", "rep", "inherits", "min", "max", "matrix", "table", "is.array", "is.element", "is.character", "exp", "all", "pmin", "pmax", "as.numeric", "proc.time", + "as.integer", "as.character", "as.matrix", ".Call", "sum", "order", "rev", "integer", "double", "as.numeric", "as.list", "as.integer", ".Call", ".FastR", "unname", "log", "lgamma", "sin", "cos", "tan", "exp", "log", "expm1", "sinh", "sinpi", "cosh", "cospi", "tanh", "tanpi", "asin", "asinh", "acos", "acosh", "atan", "atanh", "<-", "+", "-", "*", "/", "%%", "^", ":", ">=", ">", "<=", "<", "==", "!=", "||", "|", "&&", "&", "!", "%o%", "%*%", "%/%", "%in%", "{", "for", "while", "repeat", "if", "attributes", "attr")); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java index 730c1b5a772da628f5e7e2e44c66b5191f2aad91..6650047ef03bf63c405c19749b0c91b8680bbc91 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java @@ -24,14 +24,15 @@ package com.oracle.truffle.r.runtime.nodes; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.nodes.LoopNode; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeVisitor; +import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RError.Message; +import com.oracle.truffle.r.runtime.RError.RErrorException; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.conn.RConnection; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; @@ -49,6 +50,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; 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; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -237,10 +239,9 @@ public abstract class RBaseNode extends Node { return value instanceof RAbstractStringVector; } - /* - * No isXyz functions for abstract vector classes (RAbstractIntVector, etc.), because they do - * not honor implicit casts and can thus lead to unexpected behavior. - */ + protected static boolean isRAbstractListVector(Object value) { + return value instanceof RAbstractListVector; + } protected static boolean isRList(Object value) { return value instanceof RList; @@ -254,18 +255,6 @@ public abstract class RBaseNode extends Node { return value instanceof RLanguage; } - protected static boolean isRFormula(Object value) { - if (value instanceof RLanguage) { - return hasFormulaClass(value); - } - return false; - } - - @TruffleBoundary - private static boolean hasFormulaClass(Object value) { - return ((RAttributable) value).hasClass(RRuntime.FORMULA_CLASS); - } - protected static boolean isRExpression(Object value) { return value instanceof RExpression; } @@ -305,4 +294,143 @@ public abstract class RBaseNode extends Node { protected static boolean isRAttributable(Object value) { return value instanceof RAttributable; } + + /* + * Error handling-related functionality. + */ + + /** + * Find the proper context for errors or warnings produced by this node. The default behavior is + * to call getErrorContext() of the parent RBaseNode recursively. + * + * Certain types of nodes, e.g., builtins, will supply the correct context for themselves. + */ + protected RBaseNode getErrorContext() { + Node node = getParent(); + while (node != null) { + if (node instanceof RBaseNode) { + return ((RBaseNode) node).getErrorContext(); + } + if (node instanceof RootNode) { + return RError.NO_CALLER; + } + node = node.getParent(); + } + throw RInternalError.shouldNotReachHere("trying to get error context of node without parent"); + } + + /** + * @see #error(Message) + */ + public final RError error(RErrorException exception) { + CompilerDirectives.transferToInterpreter(); + throw RError.error(getErrorContext(), exception); + } + + /** + * Raises the given error with the error context determined by {@link #getErrorContext()}. This + * function is always considered to be a slow-path operation and will transferToInterpreter. + * + * @return an RError so that this function can be called as {@code throw error(...);}. + */ + public final RError error(RError.Message message) { + CompilerDirectives.transferToInterpreter(); + throw RError.error(getErrorContext(), message); + } + + /** + * @see #error(Message) + */ + public final RError error(RError.Message message, Object arg) { + CompilerDirectives.transferToInterpreter(); + throw RError.error(getErrorContext(), message, arg); + } + + /** + * @see #error(Message) + */ + public final RError error(RError.Message message, Object arg1, Object arg2) { + CompilerDirectives.transferToInterpreter(); + throw RError.error(getErrorContext(), message, arg1, arg2); + } + + /** + * @see #error(Message) + */ + public final RError error(RError.Message message, Object arg1, Object arg2, Object arg3) { + CompilerDirectives.transferToInterpreter(); + throw RError.error(getErrorContext(), message, arg1, arg2, arg3); + } + + /** + * @see #error(Message) + */ + public final RError error(RError.Message message, Object arg1, Object arg2, Object arg3, Object arg4) { + CompilerDirectives.transferToInterpreter(); + throw RError.error(getErrorContext(), message, arg1, arg2, arg3, arg4); + } + + /** + * @see #error(Message) + */ + public final RError error(RError.Message message, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { + CompilerDirectives.transferToInterpreter(); + throw RError.error(getErrorContext(), message, arg1, arg2, arg3, arg4, arg5); + } + + /** + * @see #error(Message) + */ + public final RError error(RError.Message message, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { + CompilerDirectives.transferToInterpreter(); + throw RError.error(getErrorContext(), message, arg1, arg2, arg3, arg4, arg5, arg6); + } + + @CompilationFinal boolean hasSeenWarning; + + /** + * Raises the given warning with the error context determined by {@link #getErrorContext()}. + * This function is profiled so that it will only use a real call if a warning was issued from + * this node before. + */ + public final void warning(Message msg) { + if (!hasSeenWarning) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + hasSeenWarning = true; + } + RError.warning(getErrorContext(), msg); + } + + /** + * @see #warning(Message) + */ + public final void warning(Message msg, Object arg1) { + if (!hasSeenWarning) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + hasSeenWarning = true; + } + RError.warning(getErrorContext(), msg, arg1); + } + + /** + * @see #warning(Message) + */ + public final void warning(Message msg, Object arg1, Object arg2) { + if (!hasSeenWarning) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + hasSeenWarning = true; + } + RError.warning(getErrorContext(), msg, arg1, arg2); + } + + /** + * @see #warning(Message) + */ + public final void warning(Message msg, Object arg1, Object arg2, Object arg3) { + if (!hasSeenWarning) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + hasSeenWarning = true; + } + RError.warning(getErrorContext(), msg, arg1, arg2, arg3); + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java index 0c7f9944842b3ff05069568bfb4162f5007faf52..7ae457924a12626dfd83a539a3b19ebbea093ab6 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -244,4 +244,11 @@ public interface RCodeBuilder<T> { default T call(SourceSection source, T lhs, T argument1, T argument2, T argument3) { return call(source, lhs, Arrays.asList(argument(argument1), argument(argument2), argument(argument3))); } + + /** + * Helper function: create a call with four unnamed arguments. + */ + default T call(SourceSection source, T lhs, T argument1, T argument2, T argument3, T argument4) { + return call(source, lhs, Arrays.asList(argument(argument1), argument(argument2), argument(argument3), argument(argument4))); + } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java index 8629846c531dd5fd14686a5db6e21db3d9abf77f..76d4203238bc32d70b2ea1fa11c66df3a36834e4 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java @@ -22,45 +22,18 @@ */ package com.oracle.truffle.r.runtime.nodes; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.instrumentation.Instrumentable; import com.oracle.truffle.api.nodes.UnexpectedResultException; -import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RComplexVector; -import com.oracle.truffle.r.runtime.data.RDoubleSequence; -import com.oracle.truffle.r.runtime.data.RDoubleVector; -import com.oracle.truffle.r.runtime.data.RExpression; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RIntSequence; -import com.oracle.truffle.r.runtime.data.RIntVector; -import com.oracle.truffle.r.runtime.data.RLanguage; -import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RLogicalVector; -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.RPromise; -import com.oracle.truffle.r.runtime.data.RRaw; -import com.oracle.truffle.r.runtime.data.RRawVector; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.data.RTypes; import com.oracle.truffle.r.runtime.data.RTypesGen; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; -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.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.nodes.instrumentation.RNodeWrapperFactory; @TypeSystemReference(RTypes.class) -@Instrumentable(factory = com.oracle.truffle.r.runtime.nodes.instrumentation.RNodeWrapperFactory.class) +@Instrumentable(factory = RNodeWrapperFactory.class) public abstract class RNode extends RBaseNode implements RInstrumentableNode { /** @@ -82,183 +55,26 @@ public abstract class RNode extends RBaseNode implements RInstrumentableNode { * does not start with "execute" so that the DSL does not treat it like an execute function. */ public Object visibleExecute(VirtualFrame frame) { - return execute(frame); - } - - public int executeInteger(VirtualFrame frame) throws UnexpectedResultException { - Object value = execute(frame); - assert value != null; - if (value instanceof Integer) { - return (int) value; - } else { - throw new UnexpectedResultException(value); - } - } - - public RRaw executeRRaw(VirtualFrame frame) throws UnexpectedResultException { - Object value = execute(frame); - assert value != null; - if (value instanceof RRaw) { - return (RRaw) value; - } else { - throw new UnexpectedResultException(value); - } - } - - public RAbstractVector executeRAbstractVector(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRAbstractVector(execute(frame)); - } - - public RComplex executeRComplex(VirtualFrame frame) throws UnexpectedResultException { - Object value = execute(frame); - assert value != null; - assert value != null; - if (value instanceof RComplex) { - return (RComplex) value; - } else { - throw new UnexpectedResultException(value); + Object result = execute(frame); + if (CompilerDirectives.inInterpreter() && result == null) { + throw RInternalError.shouldNotReachHere("null result in " + this.getClass().getSimpleName()); } + return result; } - public RIntSequence executeRIntSequence(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRIntSequence(execute(frame)); - } - - public RDoubleSequence executeRDoubleSequence(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRDoubleSequence(execute(frame)); - } - - public RIntVector executeRIntVector(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRIntVector(execute(frame)); - } - - public RDoubleVector executeRDoubleVector(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRDoubleVector(execute(frame)); - } - - public RRawVector executeRRawVector(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRRawVector(execute(frame)); - } - - public RComplexVector executeRComplexVector(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRComplexVector(execute(frame)); - } - - public RStringVector executeRStringVector(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRStringVector(execute(frame)); - } - - public RList executeRList(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRList(execute(frame)); - } - - public RLogicalVector executeRLogicalVector(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRLogicalVector(execute(frame)); - } - - public RAbstractDoubleVector executeRAbstractDoubleVector(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRAbstractDoubleVector(executeRAbstractVector(frame)); - } - - public RAbstractIntVector executeRAbstractIntVector(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRAbstractIntVector(executeRAbstractVector(frame)); - } - - public RAbstractComplexVector executeRAbstractComplexVector(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRAbstractComplexVector(executeRAbstractVector(frame)); - } - - public RAbstractLogicalVector executeRAbstractLogicalVector(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRAbstractLogicalVector(executeRAbstractVector(frame)); - } - - public RAbstractRawVector executeRAbstractRawVector(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRAbstractRawVector(executeRAbstractVector(frame)); - } + /* + * Execute functions with primitive return types: + */ - public RAbstractStringVector executeRAbstractStringVector(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRAbstractStringVector(executeRAbstractVector(frame)); + public int executeInteger(VirtualFrame frame) throws UnexpectedResultException { + return RTypesGen.expectInteger(execute(frame)); } public double executeDouble(VirtualFrame frame) throws UnexpectedResultException { - Object value = execute(frame); - assert value != null; - if (value instanceof Double) { - return (double) value; - } else { - throw new UnexpectedResultException(value); - } + return RTypesGen.expectDouble(execute(frame)); } public byte executeByte(VirtualFrame frame) throws UnexpectedResultException { - Object value = execute(frame); - assert value != null; - if (value instanceof Byte) { - return (byte) value; - } else { - throw new UnexpectedResultException(value); - } - } - - public Object[] executeArray(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectObjectArray(execute(frame)); - } - - public RFunction executeFunction(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRFunction(execute(frame)); - } - - public RNull executeNull(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRNull(execute(frame)); - } - - public RMissing executeMissing(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRMissing(execute(frame)); - } - - public String executeString(VirtualFrame frame) throws UnexpectedResultException { - Object value = execute(frame); - assert value != null; - if (value instanceof String) { - return (String) value; - } else { - throw new UnexpectedResultException(value); - } - } - - public REnvironment executeREnvironment(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectREnvironment(execute(frame)); - } - - public RExpression executeRExpression(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRExpression(execute(frame)); - } - - public RSymbol executeRSymbol(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRSymbol(execute(frame)); - } - - public RLanguage executeRLanguage(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRLanguage(execute(frame)); - } - - public RPromise executeRPromise(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRPromise(execute(frame)); - } - - public RAbstractContainer executeRAbstractContainer(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRAbstractContainer(execute(frame)); - } - - public RPairList executeRPairList(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRPairList(execute(frame)); - } - - public RArgsValuesAndNames executeRArgsValuesAndNames(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRArgsValuesAndNames(execute(frame)); - } - - public RType executeType(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRType(execute(frame)); + return RTypesGen.expectByte(execute(frame)); } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxLookup.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxLookup.java index eb5d2c888e7a407358daeba35a65e647cd6d8008..b4024e0347b2706a1988f5b07c39756344bd39a9 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxLookup.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxLookup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,6 +23,7 @@ package com.oracle.truffle.r.runtime.nodes; import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.runtime.Utils; /** * Represents a symbol lookup in the tree of elements that make up an R closure. @@ -55,6 +56,7 @@ public interface RSyntaxLookup extends RSyntaxElement { @Override public String getIdentifier() { + assert Utils.isInterned(identifier); return identifier; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/builtin/RBuiltinBaseNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/builtin/RBuiltinBaseNode.java new file mode 100644 index 0000000000000000000000000000000000000000..7317a9e869d31df442a2383461218bff93c7d179 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/builtin/RBuiltinBaseNode.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017, 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.runtime.nodes.builtin; + +import com.oracle.truffle.r.runtime.nodes.RBaseNode; + +public abstract class RBuiltinBaseNode extends RBaseNode { + +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java index 5f020f50ee708aa8060364812124c3eb4bf4c6ba..e3359b65efa0f40bcb1ab07bf55ccae4c7918308 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java @@ -136,13 +136,14 @@ public abstract class BinaryArithmetic extends Operation { @Override public int op(int left, int right) { - try { - return ExactMath.addExact(left, right); - } catch (ArithmeticException e) { + int r = left + right; + // TODO: not using ExactMath because of perf problems + if (((left ^ r) & (right ^ r)) < 0) { CompilerDirectives.transferToInterpreterAndInvalidate(); replace(new AddOverflow()); return INT_NA; } + return r; } @Override @@ -156,9 +157,8 @@ public abstract class BinaryArithmetic extends Operation { } @Override - @TruffleBoundary public String op(String left, String right) { - throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "character"); + throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character"); } } @@ -194,13 +194,14 @@ public abstract class BinaryArithmetic extends Operation { @Override public int op(int left, int right) { - try { - return ExactMath.subtractExact(left, right); - } catch (ArithmeticException e) { + int r = left - right; + // TODO: not using ExactMath because of perf problems + if (((left ^ right) & (left ^ r)) < 0) { CompilerDirectives.transferToInterpreterAndInvalidate(); replace(new SubtractOverflow()); return INT_NA; } + return r; } @Override @@ -214,9 +215,8 @@ public abstract class BinaryArithmetic extends Operation { } @Override - @TruffleBoundary public String op(String left, String right) { - throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "character"); + throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character"); } } @@ -251,13 +251,14 @@ public abstract class BinaryArithmetic extends Operation { @Override public int op(int left, int right) { - try { - return ExactMath.multiplyExact(left, right); - } catch (ArithmeticException e) { + long r = (long) left * (long) right; + // TODO: not using ExactMath because of perf problems + if ((int) r != r) { CompilerDirectives.transferToInterpreterAndInvalidate(); replace(new MultiplyOverflow()); return INT_NA; } + return (int) r; } @Override @@ -291,9 +292,8 @@ public abstract class BinaryArithmetic extends Operation { } @Override - @TruffleBoundary public String op(String left, String right) { - throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "character"); + throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character"); } } @@ -386,9 +386,8 @@ public abstract class BinaryArithmetic extends Operation { } @Override - @TruffleBoundary public String op(String left, String right) { - throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "character"); + throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character"); } } @@ -430,15 +429,13 @@ public abstract class BinaryArithmetic extends Operation { } @Override - @TruffleBoundary public RComplex op(double leftReal, double leftImag, double rightReal, double rightImag) { - throw RError.error(this, RError.Message.UNIMPLEMENTED_COMPLEX); + throw error(RError.Message.UNIMPLEMENTED_COMPLEX); } @Override - @TruffleBoundary public String op(String left, String right) { - throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "character"); + throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character"); } } @@ -506,15 +503,13 @@ public abstract class BinaryArithmetic extends Operation { } @Override - @TruffleBoundary public RComplex op(double leftReal, double leftImag, double rightReal, double rightImag) { - throw RError.error(this, RError.Message.UNIMPLEMENTED_COMPLEX); + throw error(RError.Message.UNIMPLEMENTED_COMPLEX); } @Override - @TruffleBoundary public String op(String left, String right) { - throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "character"); + throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character"); } } @@ -638,8 +633,8 @@ public abstract class BinaryArithmetic extends Operation { if (mult == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); mult = insert(new Multiply()); - cpow2 = insert(new CPow2()); } + ensurePow2(); } protected void ensurePow2() { @@ -992,9 +987,8 @@ public abstract class BinaryArithmetic extends Operation { } @Override - @TruffleBoundary public RComplex op(double leftReal, double leftImag, double rightReal, double rightImag) { - throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "complex"); + throw error(RError.Message.INVALID_TYPE_ARGUMENT, "complex"); } @Override @@ -1039,9 +1033,8 @@ public abstract class BinaryArithmetic extends Operation { } @Override - @TruffleBoundary public RComplex op(double leftReal, double leftImag, double rightReal, double rightImag) { - throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "complex"); + throw error(RError.Message.INVALID_TYPE_ARGUMENT, "complex"); } @Override diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryCompare.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryCompare.java index 19a58782aad3842ee1400bb6be0ef539700daf2f..12212196eb77623d5deb391293db982acead89fe 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryCompare.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryCompare.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 @@ -165,7 +165,7 @@ public abstract class BinaryCompare extends BooleanOperation { @Override public boolean op(RComplex left, RComplex right) { - throw RError.error(this, RError.Message.COMPARISON_COMPLEX); + throw error(RError.Message.COMPARISON_COMPLEX); } } @@ -197,7 +197,7 @@ public abstract class BinaryCompare extends BooleanOperation { @Override public boolean op(RComplex left, RComplex right) { - throw RError.error(this, RError.Message.COMPARISON_COMPLEX); + throw error(RError.Message.COMPARISON_COMPLEX); } } @@ -229,7 +229,7 @@ public abstract class BinaryCompare extends BooleanOperation { @Override public boolean op(RComplex left, RComplex right) { - throw RError.error(this, RError.Message.COMPARISON_COMPLEX); + throw error(RError.Message.COMPARISON_COMPLEX); } } @@ -266,7 +266,7 @@ public abstract class BinaryCompare extends BooleanOperation { @Override public boolean op(RComplex left, RComplex right) { - throw RError.error(this, RError.Message.COMPARISON_COMPLEX); + throw error(RError.Message.COMPARISON_COMPLEX); } } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryLogic.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryLogic.java index 50a29211528fdd757cdb4d03349ed18998634402..ef9b7f15c4db0cf6214be8aed4e17b16fa1facd1 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryLogic.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryLogic.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 @@ -129,7 +129,7 @@ public abstract class BinaryLogic extends BooleanOperation { @Override public boolean op(String left, String right) { - throw RError.error(this, RError.Message.OPERATIONS_NUMERIC_LOGICAL_COMPLEX); + throw error(RError.Message.OPERATIONS_NUMERIC_LOGICAL_COMPLEX); } @Override @@ -184,7 +184,7 @@ public abstract class BinaryLogic extends BooleanOperation { @Override public boolean op(String left, String right) { - throw RError.error(this, RError.Message.OPERATIONS_NUMERIC_LOGICAL_COMPLEX); + throw error(RError.Message.OPERATIONS_NUMERIC_LOGICAL_COMPLEX); } @Override diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NACheck.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NACheck.java index 6b2bbd3a2e5236671455d283ddb47f379af0254d..cbf0f6f606a1d55a6229c0d257aa2f80a02c143b 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NACheck.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NACheck.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 @@ -180,7 +180,7 @@ public final class NACheck { public RComplex convertLogicalToComplex(byte value) { if (check(value)) { - return RRuntime.createComplexNA(); + return RComplex.createNA(); } return RDataFactory.createComplex(value, 0); } @@ -194,14 +194,14 @@ public final class NACheck { public RComplex convertDoubleToComplex(double value) { if (check(value)) { - return RRuntime.createComplexNA(); + return RComplex.createNA(); } return RDataFactory.createComplex(value, 0); } public RComplex convertIntToComplex(int value) { if (check(value)) { - return RRuntime.createComplexNA(); + return RComplex.createNA(); } return RDataFactory.createComplex(value, 0); } @@ -252,7 +252,7 @@ public final class NACheck { public RComplex convertStringToComplex(String value) { if (check(value)) { - return RRuntime.createComplexNA(); + return RComplex.createNA(); } RComplex result = RRuntime.string2complexNoCheck(value); check(result); // can be NA diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java index 93c1f237119fd4495b9a25e4d2310629f79cd5e3..27203104d213c47c8406464d4daef8f9a6c816e3 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java @@ -78,6 +78,7 @@ public final class UserRNG implements RandomNumberGenerator { private abstract static class UserRNGRootNodeAdapter extends RootNode { @Child protected UserRngRFFI.UserRngRFFINode userRngRFFINode = RFFIFactory.getRFFI().getUserRngRFFI().createUserRngRFFINode(); + @SuppressWarnings("deprecation") protected UserRNGRootNodeAdapter() { super(RContext.getRRuntimeASTAccess().getTruffleRLanguage(), null, new FrameDescriptor()); } diff --git a/com.oracle.truffle.r.test.native/Makefile b/com.oracle.truffle.r.test.native/Makefile index d996da3e45a82598ff2e6d117305549b4308e679..8045621a3cdbdcff1d0ac2c40a148249fa17369e 100644 --- a/com.oracle.truffle.r.test.native/Makefile +++ b/com.oracle.truffle.r.test.native/Makefile @@ -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 @@ -26,18 +26,26 @@ export TOPDIR = $(CURDIR) # all output goes into the com.oracle.truffle.r.test project for packaging into a single distribution export MX_OUTPUT_DIR = $(abspath $(TOPDIR)/../mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test) +export REPO_DIR := $(TOPDIR)/packages/repo/src/contrib OSNAME := $(shell uname) all: + mkdir -p $(REPO_DIR) + cp packages/PACKAGES $(REPO_DIR) $(MAKE) -C urand $(MAKE) -C packages ifneq ($(OSNAME), SunOS) +ifeq ($(FASTR_RFFI),jni) $(MAKE) -C embedded endif +endif clean: $(MAKE) -C urand clean $(MAKE) -C packages clean ifneq ($(OSNAME), SunOS) +ifeq ($(FASTR_RFFI),jni) $(MAKE) -C embedded clean endif +endif + rm -f $(REPO_DIR)/* diff --git a/com.oracle.truffle.r.test.native/packages/Makefile b/com.oracle.truffle.r.test.native/packages/Makefile index 1ddf9d6a2f99f41a0887e1a39f09b52ce6003eb1..501b4d81f601f64701b52aeb8fdcd22ac1c48399 100644 --- a/com.oracle.truffle.r.test.native/packages/Makefile +++ b/com.oracle.truffle.r.test.native/packages/Makefile @@ -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 @@ -26,7 +26,7 @@ SUBDIRS = testrffi vanilla tests4 NATIVE_PROJECT = $(subst test.native,native,$(TOPDIR)) R_VERSION := $(notdir $(wildcard $(NATIVE_PROJECT)/gnur/R-*)) -GNUR_HOME := $(NATIVE_PROJECT)/gnur/$(R_VERSION) +export GNUR_HOME := $(NATIVE_PROJECT)/gnur/$(R_VERSION) GNUR_RECOMMENDED := $(wildcard $(GNUR_HOME)/src/library/Recommended/*.tgz) # We have to copy the GNU R recommended packages into this project diff --git a/com.oracle.truffle.r.test.native/packages/PACKAGES b/com.oracle.truffle.r.test.native/packages/PACKAGES new file mode 100644 index 0000000000000000000000000000000000000000..aa815aabd4bae5e8159c3df8e39594de20e152c1 --- /dev/null +++ b/com.oracle.truffle.r.test.native/packages/PACKAGES @@ -0,0 +1,17 @@ +Package: testrffi +Version: 1.0 +Depends: R +License: GPL-2 +NeedsCompilation: yes + +Package: tests4 +Version: 1.0 +Depends: R +License: GPL-2 +NeedsCompilation: no + +Package: vanilla +Version: 1.0 +Depends: R +License: GPL-2 +NeedsCompilation: no diff --git a/com.oracle.truffle.r.test.native/packages/Rutils/template.R b/com.oracle.truffle.r.test.native/packages/Rutils/template.R new file mode 100644 index 0000000000000000000000000000000000000000..33c6e2b15b1dc0f3ad10371d5ae941d091c6fc4e --- /dev/null +++ b/com.oracle.truffle.r.test.native/packages/Rutils/template.R @@ -0,0 +1,76 @@ +# +# Copyright (c) 2017, 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. +# + +expandTemplate <- function(template, ...) { + resultLength <- 1 + params <- list(...) + for (i in seq_along(params)) { + resultLength <- resultLength * length(params[[i]]) + } + index <- 1 + result <- character(resultLength) + positions <- rep(1, length(params)) + while (index <= resultLength) { + currentString <- template + for (i in seq_along(params)) { + currentPos <- positions[[i]] + currentString <- sub(paste0("%", i - 1), params[[i]][[currentPos]], currentString) + } + result[[index]] <- currentString + index <- index + 1 + + for (i in seq_along(params)) { + positions[[i]] <- positions[[i]] + 1 + if (positions[[i]] >= length(params[[i]])) { + positions[[i]] <- 1 + } else { + break + } + } + } + result +} + +initialTest <- function(libname, template, ...) { + tests <- expandTemplate(template, ...) + Rfile <- sub("\\.Rin$", ".R", commandArgs(T)) + sink(Rfile) + requireLibrary(libname) + outputTests(tests) +} + +extraTest <- function(template, ...) { + tests <- expandTemplate(template, ...) + outputTests(tests) +} + +outputTests <- function(tests) { + # errors must not cause halt, so wrap in try + for (i in seq_along(tests)) { + cat(paste0("try(", tests[[i]], ")\n")) + } +} + +requireLibrary <- function(libname) { + cat(paste0("stopifnot(require(", libname, "))\n")) +} diff --git a/com.oracle.truffle.r.test.native/packages/package.mk b/com.oracle.truffle.r.test.native/packages/package.mk index c7e7565abc99b8920745a11e406654b0bbaecda7..e98e4d3f6d7cd39d790df4fbaaf3bc93bc4dd44e 100644 --- a/com.oracle.truffle.r.test.native/packages/package.mk +++ b/com.oracle.truffle.r.test.native/packages/package.mk @@ -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 @@ -23,19 +23,35 @@ # This "builds" a test package, resulting in a tar file, # which is then loaded by the unit tests in TestRPackages. +# It uses R CMD build ... +# Currently we can't use FastR for this step as FastR isn't completely built +# when this is built (it's part of the build) +# The resulting package is stored in the "repo/src/contrib" folder + +# test packages may include .Rin files that are preprocessed to create an +# actual test file. Unfortunately while R CND check will do this, tools::testInstalledPackage +# does not (surely a bug). So we generate the files here. .PHONY: all -PKG_FILES = $(shell find $(PACKAGE)/ -type f -name '*') +PKG_FILES = $(shell find $(PACKAGE) -type f -name '*') + +PKG_TAR = $(REPO_DIR)/$(PACKAGE)_1.0.tar.gz -PKG_TAR = lib/$(PACKAGE).tar +RIN_FILES = $(shell find $(PACKAGE) -type f -name '*.Rin') +RIN_R_FILES = $(subst .Rin,.R, $(RIN_FILES)) +TEMPLATE_FILE := ../Rutils/template.R -all: $(PKG_TAR) +all: $(RIN_R_FILES) $(PKG_TAR) $(PKG_TAR): $(PKG_FILES) - mkdir -p lib - tar cf $(PKG_TAR) $(PACKAGE) + (cd $(REPO_DIR); TZDIR=/usr/share/zoneinfo/ $(GNUR_HOME)/bin/R CMD build $(CURDIR)/$(PACKAGE)) + +$(RIN_R_FILES): $(RIN_FILES) + for rf in $(RIN_FILES); do \ + TEMPLATE_FILE=$(TEMPLATE_FILE) $(GNUR_HOME)/bin/Rscript $$rf $$rf || exit 1; \ + done clean: - rm -f $(PKG_TAR) + rm -f $(PKG_TAR) $(RIN_R_FILES) diff --git a/com.oracle.truffle.r.test.native/packages/pkg-filelist b/com.oracle.truffle.r.test.native/packages/pkg-filelist new file mode 100644 index 0000000000000000000000000000000000000000..55e8fe1d119cba8985cc07155a0b23dbb05b4079 --- /dev/null +++ b/com.oracle.truffle.r.test.native/packages/pkg-filelist @@ -0,0 +1,3 @@ +vanilla +tests4 +testrffi diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/DESCRIPTION b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/DESCRIPTION index 6469b3112f0df98304623ec070f5fdbedd8ca1ab..a21a01b70702b792a0735d18e6cbe00441943d24 100644 --- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/DESCRIPTION +++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/DESCRIPTION @@ -1,9 +1,10 @@ Package: testrffi Type: Package -Title: Tests a package with native code +Title: Tests The R FFI interface Version: 1.0 -Date: 2014-08-21 +Date: 2017-02-2 Author: FastR Tester Maintainer: FastR Tester <fastr@yahoogroups.com> -Description: Tests a package with native code +Description: Tests The R FFI interface License: GPL-2 +NeedsCompilation: yes diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/man/testrffi-package.Rd b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/man/testrffi-package.Rd index f73ed8ca85e6ac0d9221cebacac42d104f2bb3d6..2ea30d34d29ec665df649be69ddc218e38fb8d9f 100644 --- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/man/testrffi-package.Rd +++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/man/testrffi-package.Rd @@ -2,14 +2,20 @@ \alias{testrffi-package} \alias{testrffi} \docType{package} -\title{Tests a package with native code} -\description{Tests a package with native code} +\title{Tests the R FFI interface} +\description{Tests the R FFI interface via a collection of R functions that +call down to native code using .Call which then typically make R FFI upcalls to +test the individual functions. The set of tests is not comprehensive. + +The individual functions are not documented here as there are far too many +and they are not intended for user-level usage. +} \details{ \tabular{ll}{ Package: \tab testrffi\cr Type: \tab Package\cr Version: \tab 1.0\cr -Date: \tab 2014-08-21\cr +Date: \tab 2017-02-20\cr License: \tab GPL-2\cr } @@ -27,5 +33,4 @@ Maintainer: fastr@yahoogroups.com } \examples{ - } diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/man/testrffi.Rd b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/man/testrffi.Rd deleted file mode 100644 index edb39851ba94c1d1f1dcf3d2f49958f85ab2f70e..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/man/testrffi.Rd +++ /dev/null @@ -1,35 +0,0 @@ -\name{testrffi} -\alias{testrffi} -%- Also NEED an '\alias' for EACH other topic documented here. -\title{ -testrffi -} -\description{ -Tests the R FFI interface -} -\usage{ -addint(2,3) -} - -\details{ - -} -\value{ -invisble NULL -} -\references{ - -} -\author{ -FastR Team -} -\note{ - -} - -\seealso{ -% -} -\examples{ -addint(2,3) -} diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c index cf78dd91c91aba55acf21084125944ee749566bd..cfddf3c96f7a168ff11332d2e75925e448986e4d 100644 --- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c +++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c @@ -32,6 +32,12 @@ static const R_CMethodDef CEntries[] = { #define CALLDEF(name, n) {#name, (DL_FUNC) &name, n} +/* It is not strictly necessary to include every C function in this table, as + * it simply enables a call to be made with the "C_name" variable style of .Call, + * as opposed to simply using the string "name". The latter is the default mechanism + * used in testrffi.c. +*/ + static const R_CallMethodDef CallEntries[] = { CALLDEF(addInt, 2), CALLDEF(addDouble, 2), diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/asTests.Rin b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/asTests.Rin new file mode 100644 index 0000000000000000000000000000000000000000..13e6e52b1dc61d61cecac36efc3e57a13c280ea1 --- /dev/null +++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/asTests.Rin @@ -0,0 +1,6 @@ +source(Sys.getenv("TEMPLATE_FILE")) + +as_values <- c("1L", "2", "2.2", "T", "integer()", "numeric()", "logical()", "character()", "c(5,6)", "c(2.3, 3.4)", "c(T, F)", "as.symbol(\"sym\")", "list()") +as_funs <- c("Char", "Integer", "Real", "Logical") + +initialTest("testrffi", "rffi.as%0(%1)", as_funs, as_values) diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/coerceTests.Rin b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/coerceTests.Rin new file mode 100644 index 0000000000000000000000000000000000000000..17d7899930e939e5af81e6f90e62d59b146c762e --- /dev/null +++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/coerceTests.Rin @@ -0,0 +1,42 @@ +source(Sys.getenv("TEMPLATE_FILE")) + +NILSXP <- as.character(0) +SYMSXP <- as.character(1) +LISTSXP <- as.character(2) +CLOSXP <- as.character(3) +ENVSXP <- as.character(4) +PROMSXP <- as.character(5) +LANGSXP <- as.character(6) +SPECIALSXP <- as.character(7) +BUILTINSXP <- as.character(8) +CHARSXP <- as.character(9) +LGLSXP <- as.character(10) +INTSXP <- as.character(13) +REALSXP <- as.character(14) +CPLXSXP <- as.character(15) +STRSXP <- as.character(16) +DOTSXP <- as.character(17) +ANYSXP <- as.character(18) +VECSXP <- as.character(19) +EXPRSXP <- as.character(20) +BCODESXP <- as.character(21) +EXTPTRSXP <- as.character(22) +WEAKREFSXP <- as.character(23) +RAWSXP <- as.character(24) +S4SXP <- as.character(25) + +coercion_values_for_expr <- c("2", "2.2", "T", "integer()", "numeric()", "logical()", "character()", "c(5,6)", "c(2.3, 3.4)", "c(T, F)", + "list()", "structure(2.2, names='b',dim=c(1,1),myattr='q')", "structure(T, names='c',dim=c(1,1),myattr='q'") + +coercion_values <- c("1L", "2", "2.2", "T", "integer()", "numeric()", "logical()", "character()", "c(5,6)", "c(2.3, 3.4)", + "c(T, F)", "list()", "structure(1L,names='a',dim=c(1,1),myattr='q')", "structure(2.2, names='b',dim=c(1,1),myattr='q')", + "structure(T, names='c',dim=c(1,1),myattr='q')", "structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'") + +coercion_modes <- c(SYMSXP, NILSXP, VECSXP, INTSXP, REALSXP, LGLSXP, STRSXP, CPLXSXP, RAWSXP) + +initialTest("testrffi", "rffi.coerceVector(%0, %1)", coercion_values, coercion_modes) + +extraTest("rffi.coerceVector(%0, %1)", coercion_values_for_expr, EXPRSXP) + +# Ignored.Unimplemented +# extraTest(paste0("rffi.coerceVector(structure(list(1,'x'), names=c('q','w'),dim=c(2,1),myattr='q'), ", EXPRSXP, ")")) diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R new file mode 100644 index 0000000000000000000000000000000000000000..92cf03a236a35b0bf896ef8fd97be859486a0817 --- /dev/null +++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R @@ -0,0 +1,24 @@ +stopifnot(require(testrffi)) + +rffi.addInt(2L, 3L) +rffi.addDouble(2, 3) +rffi.populateIntVector(5) +rffi.populateLogicalVector(5) +rffi.mkStringFromChar() +rffi.mkStringFromBytes() +rffi.null() +try(rffi.null.E()) +rffi.null.C() +rffi.isRString(character(0)) +a <- c(1L,2L,3L); rffi.iterate_iarray(a) +a <- c(1L,2L,3L); rffi.iterate_iptr(a) +rffi.dotCModifiedArguments(c(0,1,2,3)) +rffi.dotExternalAccessArgs(1L, 3, c(1,2,3), c('a', 'b'), 'b', TRUE, as.raw(12)) +rffi.dotExternalAccessArgs(x=1L, 3, c(1,2,3), y=c('a', 'b'), 'b', TRUE, as.raw(12)) +rffi.invoke12() +rffi.TYPEOF(3L) +rffi.isRString("hello") +rffi.isRString(NULL) +rffi.interactive() +x <- 1; rffi.findvar("x", globalenv()) +x <- "12345"; rffi.char_length(x) \ No newline at end of file diff --git a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation0.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation0.R new file mode 100644 index 0000000000000000000000000000000000000000..eac4f00e6447dc68ea90049b0e5b9af582133908 --- /dev/null +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation0.R @@ -0,0 +1,10 @@ +stopifnot(require(methods)) +stopifnot(require(tests4)) + +new("numeric") +setClass("foo", representation(j="numeric")); new("foo", j=42) +setClass("foo", representation(j="numeric")); typeof(new("foo", j=42)) + +setClass("foo", representation(j="numeric")); getClass("foo") + +setClass("foo"); setClass("bar", representation(j = "numeric"), contains = "foo"); is.null(getClass("foo")@prototype) diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation1.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation1.R similarity index 80% rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation1.R rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation1.R index 0a76366e675b399e127b52f04453737fc3742fb1..2f308efe17266c558d664e15058c72b29d6c8054 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation1.R +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation1.R @@ -1,5 +1,7 @@ # test from Hadley Wickham's book +stopifnot(require(methods)) +stopifnot(require(tests4)) setClass("Person", representation(name = "character", age = "numeric")) setClass("Employee", representation(boss = "Person"), contains = "Person") print(new("Person", name = "Hadley", age = 31)) diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation10.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation10.R similarity index 88% rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation10.R rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation10.R index d3c9441b27f6f202ef6ed11991884b5d1fb9bc94..eb3b1bf628f0500bf57e756c45e505644d8dfe77 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation10.R +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation10.R @@ -1,4 +1,6 @@ # test from Hadley Wickham's book +stopifnot(require(methods)) +stopifnot(require(tests4)) check_person <- function(object) { errors <- character() @@ -13,11 +15,11 @@ check_person <- function(object) { msg <- paste("Name is length ", length_name, ". Should be 1", sep = "") errors <- c(errors, msg) } - + if (length(errors) == 0) TRUE else errors } setClass("Person", representation(name = "character", age = "numeric"), validity = check_person) hadley <- new("Person", name = "Hadley", age = 31) hadley@age <- 1:10 -print(validObject(hadley)) +try(validObject(hadley)) diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation2.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation2.R similarity index 62% rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation2.R rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation2.R index e933ae21432f8ee25d785ccdeaa0987a88cf0fad..05ba0ae214e091ff415924a3807eb3daccfcbe95 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation2.R +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation2.R @@ -1,5 +1,7 @@ # test from Hadley Wickham's book +stopifnot(require(methods)) +stopifnot(require(tests4)) setClass("Person", representation(name = "character", age = "numeric")) setClass("Employee", representation(boss = "Person"), contains = "Person") -print(new("Person", name = "Hadley", age = "thirty")) +try(new("Person", name = "Hadley", age = "thirty")) diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation3.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation3.R similarity index 65% rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation3.R rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation3.R index c1c253979c5c9b03db7bab9f1e7d0b4a5e3cf427..6f596d9969082403b5f713e1d21e301cb343b7fc 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation3.R +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation3.R @@ -1,6 +1,8 @@ # IgnoreErrorContext # test from Hadley Wickham's book +stopifnot(require(methods)) +stopifnot(require(tests4)) setClass("Person", representation(name = "character", age = "numeric")) setClass("Employee", representation(boss = "Person"), contains = "Person") -print(new("Person", name = "Hadley", sex = "male")) +try(new("Person", name = "Hadley", sex = "male")) diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation4.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation4.R similarity index 77% rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation4.R rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation4.R index 8d44cf9f272c41080dd38ffc611b1031c9b87b57..0270df7258a49e1294a048a76536b8a4d9e2302a 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation4.R +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation4.R @@ -1,6 +1,8 @@ # test from Hadley Wickham's book +stopifnot(require(methods)) +stopifnot(require(tests4)) setClass("Person", representation(name = "character", age = "numeric")) setClass("Employee", representation(boss = "Person"), contains = "Person") hadley <- new("Person", name = "Hadley") -print(hadley@age) +hadley@age diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation5.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation5.R similarity index 74% rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation5.R rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation5.R index 193c85cf14f28a9cb1bdd921ae83e5e063a9a0d9..998abefbd13e9fd764476c6c084d42f0004d6695 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation5.R +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation5.R @@ -1,6 +1,8 @@ # test from Hadley Wickham's book +stopifnot(require(methods)) +stopifnot(require(tests4)) setClass("Person", representation(name = "character", age = "numeric")) setClass("Employee", representation(boss = "Person"), contains = "Person") hadley <- new("Person", name = "Hadley") -print(slot(hadley, "age")) +slot(hadley, "age") diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation6.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation6.R similarity index 74% rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation6.R rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation6.R index 54b498d595b508e75c54db15a7f9b2aa5aebbd93..e131736c5a91de6e77ab3ad59e2310037e6707a8 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation6.R +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation6.R @@ -1,5 +1,7 @@ # test from Hadley Wickham's book +stopifnot(require(methods)) +stopifnot(require(tests4)) setClass("Person", representation(name = "character", age = "numeric"), prototype(name = NA_character_, age = NA_real_)) hadley <- new("Person", name = "Hadley") -print(hadley@age) +hadley@age diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation7.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation7.R similarity index 86% rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation7.R rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation7.R index bb07265572319c1ef624c7511ab1b29a451e8096..13b43791850231cf5c99592672ca9d4f5dc5e212 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation7.R +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation7.R @@ -1,5 +1,7 @@ # test from Hadley Wickham's book +stopifnot(require(methods)) +stopifnot(require(tests4)) check_person <- function(object) { errors <- character() length_age <- length(object@age) @@ -13,9 +15,9 @@ check_person <- function(object) { msg <- paste("Name is length ", length_name, ". Should be 1", sep = "") errors <- c(errors, msg) } - + if (length(errors) == 0) TRUE else errors } setClass("Person", representation(name = "character", age = "numeric"), validity = check_person) -print(new("Person", name = "Hadley")) +try(new("Person", name = "Hadley")) diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation8.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation8.R similarity index 84% rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation8.R rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation8.R index 75c2b63b397b11e9a1c3390672578da110fd7d6d..c0d0057cf1f7d2dea17d6225d33a426f9eb9237a 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation8.R +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation8.R @@ -1,5 +1,7 @@ # test from Hadley Wickham's book +stopifnot(require(methods)) +stopifnot(require(tests4)) check_person <- function(object) { errors <- character() length_age <- length(object@age) @@ -13,9 +15,9 @@ check_person <- function(object) { msg <- paste("Name is length ", length_name, ". Should be 1", sep = "") errors <- c(errors, msg) } - + if (length(errors) == 0) TRUE else errors } setClass("Person", representation(name = "character", age = "numeric"), validity = check_person) -print(new("Person", name = "Hadley", age = 1:10)) +try(new("Person", name = "Hadley", age = 1:10)) diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation9.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation9.R similarity index 85% rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation9.R rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation9.R index 8aa98b24670780875ac300c13241b2dc938ff889..3d6e712d4e92398fb4eb16652cd582e7edd97abd 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation9.R +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation9.R @@ -1,5 +1,7 @@ # test from Hadley Wickham's book +stopifnot(require(methods)) +stopifnot(require(tests4)) check_person <- function(object) { errors <- character() length_age <- length(object@age) @@ -13,10 +15,9 @@ check_person <- function(object) { msg <- paste("Name is length ", length_name, ". Should be 1", sep = "") errors <- c(errors, msg) } - + if (length(errors) == 0) TRUE else errors } setClass("Person", representation(name = "character", age = "numeric"), validity = check_person) -print(new("Person", name = "Hadley", age = 31)) - +new("Person", name = "Hadley", age = 31) diff --git a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/conversions.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/conversions.R new file mode 100644 index 0000000000000000000000000000000000000000..6881b18794ad0094acbc50fc5c061eb392289847 --- /dev/null +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/conversions.R @@ -0,0 +1,8 @@ +stopifnot(require(methods)) +stopifnot(require(tests4)) + +x<-42; isS4(x) +x<-42; y<-asS4(x); isS4(y) +isS4(NULL) +asS4(NULL); isS4(NULL) +asS4(7:42) diff --git a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/inspect.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/inspect.R new file mode 100644 index 0000000000000000000000000000000000000000..a3af8df2ad1eb5866fa4ffce574872e8c484284d --- /dev/null +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/inspect.R @@ -0,0 +1,7 @@ +stopifnot(require(methods)) +stopifnot(require(tests4)) + +tests4:::inspect.vehicle(new("Car"), new("Inspector")) +tests4:::inspect.vehicle(new("Truck"), new("Inspector")) +tests4:::inspect.vehicle(new("Car"), new("StateInspector")) +tests4:::inspect.vehicle(new("Truck"), new("StateInspector")) diff --git a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods0.R.bug b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods0.R.bug new file mode 100644 index 0000000000000000000000000000000000000000..53b1e01861f8cc95aff7a36f77e1bb3c37f9e99a --- /dev/null +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods0.R.bug @@ -0,0 +1,15 @@ +# this has differences that the fuzzy compare cannot cope with + +stopifnot(require(methods)) +stopifnot(require(tests4)) + +setGeneric("gen", function(object) standardGeneric("gen")); res<-print(gen); removeGeneric("gen"); res +gen<-function(object) 0; setGeneric("gen"); res<-print(gen); removeGeneric("gen"); res + +gen<-function(object) 0; setGeneric("gen"); setClass("foo", representation(d="numeric")); setMethod("gen", signature(object="foo"), function(object) object@d); res<-print(gen(new("foo", d=42))); removeGeneric("gen"); res + +setClass("foo", representation(d="numeric")); setClass("bar", contains="foo"); setGeneric("gen", function(o) standardGeneric("gen")); setMethod("gen", signature(o="foo"), function(o) "FOO"); setMethod("gen", signature(o="bar"), function(o) "BAR"); res<-print(c(gen(new("foo", d=7)), gen(new("bar", d=42)))); removeGeneric("gen"); res + +setGeneric("gen", function(o) standardGeneric("gen")); res<-print(setGeneric("gen", function(o) standardGeneric("gen"))); removeGeneric("gen"); res + +setClass("foo"); setMethod("diag<-", "foo", function(x, value) 42); removeMethod("diag<-", "foo"); removeGeneric("diag<-"); removeClass("foo") diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods1.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods1.R similarity index 92% rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods1.R rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods1.R index 24dde5f0dff4b61e4ce8f9c7ba2bfff1701afa08..35c6b6705850f3ef63adb7a8d084fa253a861fb2 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods1.R +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods1.R @@ -1,5 +1,7 @@ # test from Hadley Wickham's book +stopifnot(require(methods)) +stopifnot(require(tests4)) setGeneric("sides", function(object) { standardGeneric("sides") }) diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods2.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods2.R similarity index 92% rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods2.R rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods2.R index 8afba8e7e92ea0a455904dfe1aa76373aaa7480c..375a0a9b873a60296880f29da2779c976addd55d 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods2.R +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods2.R @@ -1,5 +1,7 @@ # test from Hadley Wickham's book +stopifnot(require(methods)) +stopifnot(require(tests4)) setGeneric("sides", function(object) { standardGeneric("sides") }) diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods3.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods3.R similarity index 73% rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods3.R rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods3.R index a944995797977d03696a9ad21a9324c3e6188a4d..d8d792ffabcb7f5ce5a88f9fc52d37b8efbf1f68 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods3.R +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods3.R @@ -1,5 +1,7 @@ # test from Hadley Wickham's book +stopifnot(require(methods)) +stopifnot(require(tests4)) setGeneric("sides", valueClass = "numeric", function(object) { standardGeneric("sides") }) @@ -11,4 +13,4 @@ setClass("Square", contains = "Polygon") # setClass("Circle", contains = "Shape") setMethod("sides", signature("Triangle"), function(object) "three") -tryCatch({sides(new("Triangle"))}, error = function(e) { removeGeneric("sides"); stop(e) }) +try(tryCatch({sides(new("Triangle"))}, error = function(e) { removeGeneric("sides"); stop(e) })) diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods4.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods4.R similarity index 75% rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods4.R rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods4.R index a18ecd900b3ef2396ac98a4256d38c49d6b4c0b7..b9df6ef17f1afafb341b49555024536d1ead8fa7 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods4.R +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods4.R @@ -1,11 +1,13 @@ # test from Hadley Wickham's book +stopifnot(require(methods)) +stopifnot(require(tests4)) setClass("A") setClass("A1", contains = "A") setClass("A2", contains = "A1") setClass("A3", contains = "A2") -setGeneric("foo", function(a, b) standardGeneric("foo")) +setGeneric("foo", function(a, b) standardGeneric("foo")) setMethod("foo", signature("A1", "A2"), function(a, b) "1-2") setMethod("foo", signature("A2", "A1"), function(a, b) "2-1") diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods5.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods5.R similarity index 89% rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods5.R rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods5.R index 69b502a7d2bff0a00d6d78de17f790d63814d348..e51df55343658467bfa923daab1f8df27a36a4c9 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods5.R +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods5.R @@ -1,5 +1,7 @@ # test from Hadley Wickham's book (slightly augmented) +stopifnot(require(methods)) +stopifnot(require(tests4)) setClass("Vehicle") setClass("Truck", contains = "Vehicle") setClass("Car", contains = "Vehicle") @@ -26,4 +28,4 @@ setMethod("inspect.vehicle", }) inspect.vehicle(new("Car"), new("Inspector")) -removeGeneric("inspect.vehicle"); +removeGeneric("inspect.vehicle") diff --git a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slotAccess.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slotAccess.R new file mode 100644 index 0000000000000000000000000000000000000000..f4c92749c73436d9931df8acdd9559523798cb71 --- /dev/null +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slotAccess.R @@ -0,0 +1,25 @@ +stopifnot(require(methods)) +stopifnot(require(tests4)) + +`@`(getClass("ClassUnionRepresentation"), "virtual") +`@`(getClass("ClassUnionRepresentation"), "virtual") +try(`@`(getClass("ClassUnionRepresentation"), c("virtual", "foo"))) +getClass("ClassUnionRepresentation")@virtual +getClass("ClassUnionRepresentation")@.S3Class +c(42)@.Data +x<-42; `@`(x, ".Data") +x<-42; `@`(x, .Data) +x<-42; slot(x, ".Data") +setClass("foo", contains="numeric"); x<-new("foo"); res<-x@.Data; removeClass("foo"); res +setClass("foo", contains="numeric"); x<-new("foo"); res<-slot(x, ".Data"); removeClass("foo"); res +try(getClass("ClassUnionRepresentation")@foo) +try(c(42)@foo) +x<-42; attr(x, "foo")<-7; try(x@foo) +x<-42; attr(x, "foo")<-7; slot(x, "foo") +x<-c(42); class(x)<-"bar"; try(x@foo) +x<-getClass("ClassUnionRepresentation"); slot(x, "virtual") +x<-getClass("ClassUnionRepresentation"); try( slot(x, virtual)) +x<-function() 42; attr(x, "foo")<-7; y<-asS4(x); y@foo +x<-NULL; try(`@`(x, foo)) +x<-NULL; try(x@foo) +x<-paste0(".", "Data"); y<-42; slot(y, x) diff --git a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slotUpdate.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slotUpdate.R new file mode 100644 index 0000000000000000000000000000000000000000..f10261b0573b76d46718af73e12acce0cb59d0bc --- /dev/null +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slotUpdate.R @@ -0,0 +1,12 @@ +stopifnot(require(methods)) +stopifnot(require(tests4)) + +x<-getClass("ClassUnionRepresentation"); x@virtual<-TRUE; x@virtual +x<-getClass("ClassUnionRepresentation"); slot(x, "virtual", check=TRUE)<-TRUE; x@virtual +x<-initialize@valueClass; initialize@valueClass<-"foo"; initialize@valueClass<-x + +x<-function() 42; attr(x, "foo")<-7; try(y@foo<-42) +x<-function() 42; attr(x, "foo")<-7; try(slot(y, "foo")<-42) +x<-function() 42; attr(x, "foo")<-7; y<-asS4(x); try(y@foo<-42) +x<-NULL; try(`@<-`(x, foo, "bar")) +x<-NULL; try(x@foo<-"bar") diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/slot_access1.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slot_access1.R similarity index 80% rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/slot_access1.R rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slot_access1.R index a1743cc28aa17f4131607596ae5d76c117905785..a0160b4bb98a0b33db56bdc99ad484e08a1fe4fa 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/slot_access1.R +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slot_access1.R @@ -1,5 +1,7 @@ # test from Hadley Wickham's book +stopifnot(require(methods)) +stopifnot(require(tests4)) setClass("Person", representation(name = "character", age = "numeric"), prototype(name = NA_character_, age = NA_real_)) hadley <- new("Person", name = "Hadley") print(getSlots("Person")) diff --git a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/stdgeneric.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/stdgeneric.R new file mode 100644 index 0000000000000000000000000000000000000000..0293d845770286a283a609d8abcd03b14ce3acec --- /dev/null +++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/stdgeneric.R @@ -0,0 +1,8 @@ +stopifnot(require(methods)) +stopifnot(require(tests4)) + +try(standardGeneric(42)) +try(standardGeneric(character())) +try(standardGeneric("")) +try(standardGeneric("foo", 42)) +x<-42; class(x)<-character(); try(standardGeneric("foo", x)) diff --git a/com.oracle.truffle.r.test.native/packages/vanilla/vanilla/man/vanilla.Rd b/com.oracle.truffle.r.test.native/packages/vanilla/vanilla/man/vanilla.Rd deleted file mode 100644 index 21eb5aea52a0a02c81da888f0f2b011a8a8fa4c5..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.test.native/packages/vanilla/vanilla/man/vanilla.Rd +++ /dev/null @@ -1,35 +0,0 @@ -\name{vanilla} -\alias{vanilla} -%- Also NEED an '\alias' for EACH other topic documented here. -\title{ -vanilla -} -\description{ -prints A vaniila R package -} -\usage{ -vanilla() -} - -\details{ - -} -\value{ -invisble NULL -} -\references{ - -} -\author{ -FastR Team -} -\note{ - -} - -\seealso{ -% -} -\examples{ -vanilla() -} diff --git a/com.oracle.truffle.r.test.native/packages/vanilla/vanilla/tests/vanilla.R b/com.oracle.truffle.r.test.native/packages/vanilla/vanilla/tests/vanilla.R new file mode 100644 index 0000000000000000000000000000000000000000..e9992f04c4310262d137cc241c22eaeb8d8ed2bb --- /dev/null +++ b/com.oracle.truffle.r.test.native/packages/vanilla/vanilla/tests/vanilla.R @@ -0,0 +1,5 @@ +stopifnot(require(vanilla)) + +vanilla() +functionTest(c(1,2,3,4,5,6),8:10) +r<-42; vanilla::foo(r)<-7; r diff --git a/com.oracle.truffle.r.test.cran/initial.package.blacklist b/com.oracle.truffle.r.test.packages/initial.package.blacklist similarity index 100% rename from com.oracle.truffle.r.test.cran/initial.package.blacklist rename to com.oracle.truffle.r.test.packages/initial.package.blacklist diff --git a/com.oracle.truffle.r.test.cran/ok.packages b/com.oracle.truffle.r.test.packages/ok.packages similarity index 100% rename from com.oracle.truffle.r.test.cran/ok.packages rename to com.oracle.truffle.r.test.packages/ok.packages diff --git a/com.oracle.truffle.r.test.cran/r/install.package.R b/com.oracle.truffle.r.test.packages/r/install.package.R similarity index 93% rename from com.oracle.truffle.r.test.cran/r/install.package.R rename to com.oracle.truffle.r.test.packages/r/install.package.R index e3a4f99e853e2c75749bedb5a4ef4bbd04e959e3..70e6958084013258ecd495d18eeca3aa7c80d827 100644 --- a/com.oracle.truffle.r.test.cran/r/install.package.R +++ b/com.oracle.truffle.r.test.packages/r/install.package.R @@ -21,7 +21,7 @@ # questions. # -# A script to do a single package installation (+dependents), called from install.cran.packages.R. +# A script to do a single package installation (+dependents), called from install.packages.R. # It exists as a separate script only to avoid internal FastR errors from killing the # entire installation process for multiple package installation tests. @@ -33,14 +33,13 @@ args <- commandArgs(TRUE) parse.args <- function() { if (length(args)) { pkgname <<- args[[1]] - contriburl<<- args[[2]] + contriburl <<- strsplit(args[[2]], ",")[[1]] lib.install <<- args[[3]] } } run <- function() { parse.args() - # TODO install Suggests for vingette testing install.packages(pkgname, contriburl=contriburl, type="source", lib=lib.install, INSTALL_opts="--install-tests") } diff --git a/com.oracle.truffle.r.test.cran/r/install.cran.packages.R b/com.oracle.truffle.r.test.packages/r/install.packages.R similarity index 82% rename from com.oracle.truffle.r.test.cran/r/install.cran.packages.R rename to com.oracle.truffle.r.test.packages/r/install.packages.R index a92c95ff4a23de6e5b9ec66b9e0a38d7e6d14ade..01facbd88a767347d392589cdeaedb117e837654 100644 --- a/com.oracle.truffle.r.test.cran/r/install.cran.packages.R +++ b/com.oracle.truffle.r.test.packages/r/install.packages.R @@ -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 @@ -21,7 +21,7 @@ # questions. # -# A script to install and optionally test CRAN packages, with a blacklist mechanism starting +# A script to install and optionally test packages (typically from CRAN), with a blacklist mechanism starting # from a known set of packages that we cannot handle, e.g. Rcpp (due to C++) # By default all packages are candidates for installation, but this # can be limited in the following ways: @@ -31,21 +31,34 @@ # 3. from the set of installed packages found in the lib install directory (option --pkg-list-installed) # (useful primarily for testing a set of pre-installed packages -# By default, we use the CRAN mirror specified by --cran-mirror or env var CRAN_MIRROR. -# If unset, defaults to "http://cran.cnr.berkeley.edu/" -# However, a local copy of the CRAN repo can be used either by setting the LOCAL_CRAN_REPO env variable or setting --contrib-url +# This script can install packages from a variety of sources PROVIDED that they follow the +# structure used by CRAN, which is the main source of packages in the R world. (I.e. they support +# utils::available.packages and utils::install.packages). +# Other sources include: +# +# BioConductor +# GitHub +# FastR internal packages + +# BioConductor has it's own install mechanism but it is layered on the CRAN model. + +# A list of repos can be provided with the --repos argument, which ia comma separated string of name=value pairs. +# The names "CRAN", "BIOC" and "FASTR" are understood and have default values. +# By default, we use the CRAN mirror specified in the --repos argument or env var CRAN_MIRROR. +# The default value for --repos is "CRAN=http://cran.cnr.berkeley.edu" # Packages are installed into the directory specified by the --lib arg (or R_LIBS_USER env var) -# Blacklisted packages nor their dependents will not be installed. By default the list of blacklisted -# packages will be read from the file in the --blacklist-file arg or the PACKAGE_BLACKLIST env var. -# If unset, defaults to "package.blacklist", and will be created if necessary. The initial set of -# blacklisted packages are read from the file specified by --initial-blacklist-file (defaults to -# value of env var INITIAL_PACKAGE_BLACKLIST or initial.package.blacklist if unset). This is -# DCF file with entries of the form: +# By default, blacklisted packages nor their dependents will not be installed. The list of blacklisted +# packages will be read from the file in the --blacklist-file arg (defaults to "package.blacklist"), +# and will be created if necessary. The initial set of blacklisted packages are read from the file specified by +# --initial-blacklist-file (defaults to "com.oracle.truffle.r.test.packages/initial.package.blacklist"). +# This is a DCF file with entries of the form: # Package: name # Reason: reason +# The --ignore-blacklist option can be used to suppress the use of the blacklist. + # The env var R_LIBS_USER or the option --lib must be set to the directory where the install should take place. # N.B. --lib works for installation. However, when running tests ( --run-tests), it does not and # R_LIBS_USER must be set instead (as well) since some of the test code has explicit "library(foo)" calls @@ -91,7 +104,8 @@ args <- commandArgs(TRUE) usage <- function() { - cat(paste("usage: Rscript [--contriburl url] [--cran-mirror url] ", + cat(paste("usage: Rscript ", + "[--repos name=value,...]", "[--verbose | -v] [-V] [--dryrun]", "[--no-install | -n] ", "[--create-blacklist] [--blacklist-file file] [--ignore-blacklist]", @@ -243,34 +257,47 @@ abort <- function(msg) { quit("no", status=100) } -set.contriburl <- function() { - # if contriburl is set explicitly that's all we need - if (!is.na(contriburl)) { - return(contriburl) - } - - # check for env var setting - contriburl <<- Sys.getenv("LOCAL_CRAN_REPO", unset=NA) - if (!is.na(contriburl)) { - return(contriburl) - } - - # set from the cran-mirror value - if (is.na(cran.mirror)) { - # not set on command line - cran.mirror <<- Sys.getenv("CRAN_MIRROR", unset = "http://cran.cnr.berkeley.edu/") +set.repos <- function() { + # Based on the value of repos.list we set the "repos" option + # which is used by available.packages etc. + repos <- character() + for (repo in repo.list) { + parts <- strsplit(repo, "=", fixed=T)[[1]] + name <- parts[[1]] + if (length(parts) > 1) { + uri <- parts[[2]] + } else { + uri <- NA_character_ + } + if (name == "BIOC") { + # source("http://bioconductor.org/biocLite.R") + # repos["BIOC"] <- biocinstallRepos()[1] + # above is correct but provokes bug: + # Error in read.table(): more columns than column names + repos[["BIOC"]] <- "https://bioconductor.org/packages/3.4/bioc" + } else if (name == "CRAN") { + if (is.na(uri)) { + # not set on command line + cran.mirror <<- Sys.getenv("CRAN_MIRROR", unset = "http://cran.cnr.berkeley.edu/") + } else { + cran.mirror <- uri + } + repos[["CRAN"]] <- cran.mirror + } else if (name == "FASTR") { + # set the FastR internal repo + repos[["FASTR"]] <- paste0("file://", normalizePath("com.oracle.truffle.r.test.native/packages/repo")) + } else { + # User defined + repos[[name]] <- uri + } } - r <- getOption("repos") - r["CRAN"] <- cran.mirror - options(repos = r) - contriburl <<- contrib.url(r, "source") - contriburl + options(repos = repos) } set.package.blacklist <- function() { if (is.na(blacklist.file)) { # not set on command line - blacklist.file <<- Sys.getenv("PACKAGE_BLACKLIST", unset="package.blacklist") + blacklist.file <<- "package.blacklist" } if (!create.blacklist.file && !ignore.blacklist) { if (!file.exists(blacklist.file)) { @@ -280,12 +307,12 @@ set.package.blacklist <- function() { } } -this.package <- "com.oracle.truffle.r.test.cran" +this.package <- "com.oracle.truffle.r.test.packages" set.initial.package.blacklist <- function() { if (is.na(initial.blacklist.file)) { # not set on command line - initial.blacklist.file <<- Sys.getenv("INITIAL_PACKAGE_BLACKLIST", unset=file.path(this.package, "initial.package.blacklist")) + initial.blacklist.file <<- file.path(this.package, "initial.package.blacklist") } } @@ -357,7 +384,7 @@ check.installed.pkgs <- function() { pkgs.ok } -# find the available packages from contriburl and match those against the +# find the available packages and match those against the # requested set of candidate packages # sets global variables avail.pkgs and toinstall.pkgs, the latter being # of the same type as avail.pkgs but containing only those packages to install @@ -370,14 +397,14 @@ get.pkgs <- function() { quit(save="no", status=100) } tryCatch({ - avail.pkgs <<- available.packages(contriburl=contriburl, type="source") + avail.pkgs <<- available.packages(type="source") }, warning=my.warning) # Owing to a FastR bug, we may not invoke the handler above, but # if length(avail.pkgs) == 0, that also means it failed if (length(avail.pkgs) == 0) { if (!quiet) { - print("Fatal error: no packages found in repo") + print("Fatal error: no packages found in repo(s)") } quit(save="no", status=100) } @@ -399,27 +426,38 @@ get.pkgs <- function() { in.installed <- function(x) x["Package"] %in% installed.pkgs - basic.exclude <- function(x) { - in.installed(x) || in.blacklist(x) + basic.exclude <- function(x, exclude.installed = T) { + in.blacklist(x) || ifelse(exclude.installed, in.installed(x), F) } - # either pkg.pattern is set or pkg.filelist but not both (checked earlier) - # if inverting, alter sense of the basic match but still exclude blacklist/installed - if (!is.na(pkg.filelistfile)) { - if (invert.pkgset) { - match.fun <- function(x) !in.filelist(x) && !basic.exclude(x) - } else { - match.fun <- function(x) in.filelist(x) && !basic.exclude(x) - } - } else { - if (invert.pkgset) { - match.fun <- function(x) !in.pattern(x) && !basic.exclude(x) + set.match.fun <- function(exclude.installed = T) { + # either pkg.pattern is set or pkg.filelist but not both (checked earlier) + # if inverting, alter sense of the basic match but still exclude blacklist/installed + if (!is.na(pkg.filelistfile)) { + if (invert.pkgset) { + match.fun <- function(x) !in.filelist(x) && !basic.exclude(x, exclude.installed) + } else { + match.fun <- function(x) in.filelist(x) && !basic.exclude(x, exclude.installed) + } } else { - match.fun <- function(x) in.pattern(x) && !basic.exclude(x) + if (invert.pkgset) { + match.fun <- function(x) !in.pattern(x) && !basic.exclude(x, exclude.installed) + } else { + match.fun <- function(x) in.pattern(x) && !basic.exclude(x, exclude.installed) + } } } + + match.fun <- set.match.fun() + matched.avail.pkgs <- apply(avail.pkgs, 1, match.fun) - toinstall.pkgs <<-avail.pkgs[matched.avail.pkgs, , drop=F] + toinstall.pkgs <<- avail.pkgs[matched.avail.pkgs, , drop=F] + + if (length(toinstall.pkgs) == 0 && !use.installed.pkgs) { + print("Fatal error: requested package(s) found in repo(s)") + quit(save="no", status=100) + + } if (!is.na(random.count)) { # install random.count packages taken at random from toinstall.pkgs @@ -430,15 +468,22 @@ get.pkgs <- function() { test.pkgnames[[i]] <- test.avail.pkgnames[[rands[[i]]]] } } else { - test.pkgnames <- rownames(toinstall.pkgs) - if (!is.na(count.daily)) { - # extract count from index given by yday - npkgs <- length(test.pkgnames) - yday <- as.POSIXlt(Sys.Date())$yday - chunk <- as.integer(npkgs / count.daily) - start <- (yday %% chunk) * count.daily - end <- ifelse(start + count.daily > npkgs, npkgs, start + count.daily - 1) - test.pkgnames <- test.pkgnames[start:end] + if (length(toinstall.pkgs) == 0) { + # use.installed.pkgs == TRUE (see above) + match.fun <- set.match.fun(F) + matched.avail.pkgs <- apply(avail.pkgs, 1, match.fun) + test.pkgnames <- rownames(avail.pkgs[matched.avail.pkgs, , drop=F]) + } else { + test.pkgnames <- rownames(toinstall.pkgs) + if (!is.na(count.daily)) { + # extract count from index given by yday + npkgs <- length(test.pkgnames) + yday <- as.POSIXlt(Sys.Date())$yday + chunk <- as.integer(npkgs / count.daily) + start <- (yday %% chunk) * count.daily + end <- ifelse(start + count.daily > npkgs, npkgs, start + count.daily - 1) + test.pkgnames <- test.pkgnames[start:end] + } } } @@ -654,7 +699,7 @@ do.it <- function() { } # Should package "x" be included in the install? -# No, if it is inthe blacklist set (what about --ignore-blacklist?) +# No, if it is in the blacklist set (what about --ignore-blacklist?) # Nor if it is in ok.pkg.filelist (what does this achieve) include.package <- function(x, blacklist) { return (!(x["Package"] %in% blacklist || x["Package"] %in% ok.pkg.filelist)) @@ -674,7 +719,7 @@ install.pkg <- function(pkgname) { if (run.mode == "system") { system.install(pkgname) } else if (run.mode == "internal") { - install.packages(pkgname, contriburl=contriburl, type="source", lib=lib.install, INSTALL_opts="--install-tests") + install.packages(pkgname, type="source", lib=lib.install, INSTALL_opts="--install-tests") } else if (run.mode == "context") { stop("context run-mode not implemented\n") } @@ -684,20 +729,34 @@ install.pkg <- function(pkgname) { return(rc) } +# when testing under graalvm, fastr is not built so we must use the (assumed) sibling gnur repo +check_graalvm <- function() { + if (!is.na(Sys.getenv('FASTR_GRAALVM', unset=NA)) || !is.na(Sys.getenv('GRAALVM_FASTR', unset=NA))) { + normalizePath(Sys.glob(file.path("..", 'gnur', 'gnur', 'R-*'))) + } else { + NA + } +} + gnu_rscript <- function() { - rv <- R.Version() - dirv <- paste0('R-', rv$major, '.', rv$minor) - file.path("com.oracle.truffle.r.native/gnur", dirv, 'bin/Rscript') + gnur_dir <- check_graalvm() + if (!is.na(gnur_dir)) { + file.path(gnur_dir, 'bin', 'Rscript') + } else { + rv <- R.Version() + dirv <- paste0('R-', rv$major, '.', rv$minor) + file.path("com.oracle.truffle.r.native/gnur", dirv, 'bin', 'Rscript') + } } system.install <- function(pkgname) { - script <- normalizePath("com.oracle.truffle.r.test.cran/r/install.package.R") + script <- normalizePath("com.oracle.truffle.r.test.packages/r/install.package.R") if (is.fastr()) { rscript = file.path(R.home(), "bin", "Rscript") } else { rscript = gnu_rscript() } - args <- c(script, pkgname, contriburl, lib.install) + args <- c(script, pkgname, paste0(contrib.url(getOption("repos"), "source"), collapse=","), lib.install) rc <- system2(rscript, args) rc } @@ -735,7 +794,7 @@ is.fastr <- function() { } system.test <- function(pkgname) { - script <- normalizePath("com.oracle.truffle.r.test.cran/r/test.package.R") + script <- normalizePath("com.oracle.truffle.r.test.packages/r/test.package.R") if (is.fastr()) { rscript = file.path(R.home(), "bin", "Rscript") } else { @@ -765,8 +824,6 @@ parse.args <- function() { a <- args[1L] if (a %in% c("-h", "--help")) { usage() - } else if (a == "--contriburl") { - contriburl <<- get.argvalue() } else if (a == "--verbose" || a == "-v") { verbose <<- T } else if (a == "-V") { @@ -786,8 +843,8 @@ parse.args <- function() { blacklist.file <<- get.argvalue() } else if (a == "--initial-blacklist-file") { initial.blacklist.file <<- get.argvalue() - } else if (a == "--cran-mirror") { - cran.mirror <<- get.argvalue() + } else if (a == "--repos") { + repo.list <<- strsplit(get.argvalue(), ",")[[1]] } else if (a == "--random") { random.count <<- as.integer(get.argvalue()) if (is.na(random.count)) { @@ -846,6 +903,9 @@ parse.args <- function() { if (is.na(pkg.pattern) && is.na(pkg.filelistfile)) { pkg.pattern <<- "^.*" } + if (!install) { + use.installed.pkgs <<- T + } # list.versions is just that if (list.versions) { install <<- F @@ -856,7 +916,6 @@ parse.args <- function() { cat.args <- function() { if (verbose) { cat("cran.mirror:", cran.mirror, "\n") - cat("contriburl:", contriburl, "\n") cat("initial.blacklist.file:", initial.blacklist.file, "\n") cat("blacklist.file:", blacklist.file, "\n") cat("lib.install:", lib.install, "\n") @@ -866,7 +925,6 @@ cat.args <- function() { cat("create.blacklist.file:", create.blacklist.file, "\n") cat("ignore.blacklist:", ignore.blacklist, "\n") cat("pkg.pattern:", pkg.pattern, "\n") - cat("contriburl:", contriburl, "\n") cat("random.count:", random.count, "\n") cat("count.daily:", count.daily, "\n") cat("run.mode:", run.mode, "\n") @@ -911,7 +969,7 @@ run.setup <- function() { parse.args() check.libs() check.pkgfilelist() - set.contriburl() + set.repos() set.initial.package.blacklist() set.package.blacklist() lib.install <<- normalizePath(lib.install) @@ -924,8 +982,8 @@ run <- function() { } quiet <- F +repo.list <- c("CRAN") cran.mirror <- NA -contriburl <- NA blacklist.file <- NA initial.blacklist.file <- NA lib.install <- NA diff --git a/com.oracle.truffle.r.test.cran/r/test.package.R b/com.oracle.truffle.r.test.packages/r/test.package.R similarity index 95% rename from com.oracle.truffle.r.test.cran/r/test.package.R rename to com.oracle.truffle.r.test.packages/r/test.package.R index 9c24412015fa26cbf2afc348e1e85b123346889d..40ceb1276ece878615fb218c7556fcbe05199c77 100644 --- a/com.oracle.truffle.r.test.cran/r/test.package.R +++ b/com.oracle.truffle.r.test.packages/r/test.package.R @@ -21,7 +21,7 @@ # questions. # -# A script to do a single package test, called from install.cran.packages.R. +# A script to do a single package test, called from install.packages.R. # It exists as a separate script only to avoid internal FastR errors from killing the # entire test process for multiple package tests. diff --git a/com.oracle.truffle.r.test.cran/recommended b/com.oracle.truffle.r.test.packages/recommended similarity index 100% rename from com.oracle.truffle.r.test.cran/recommended rename to com.oracle.truffle.r.test.packages/recommended diff --git a/com.oracle.truffle.r.test.cran/top100 b/com.oracle.truffle.r.test.packages/top100 similarity index 100% rename from com.oracle.truffle.r.test.cran/top100 rename to com.oracle.truffle.r.test.packages/top100 diff --git a/com.oracle.truffle.r.test.cran/top100test b/com.oracle.truffle.r.test.packages/top100test similarity index 100% rename from com.oracle.truffle.r.test.cran/top100test rename to com.oracle.truffle.r.test.packages/top100test 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 366264daa34980cb3909e3aed54f68207321fb9f..c700f6b474620a0bc5151920c9259f33a5920e76 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 @@ -1,118 +1,410 @@ -##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests# -#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation1.R") } -An object of class "Person" -Slot "name": -[1] "Hadley" +##com.oracle.truffle.r.test.S4.TestR5.testAllocation# +#env0 <- new.env(); setRefClass('Foo17R5', where = env0); ls(topenv(parent.frame()), all.names = T); ls(env0, all.names = T) +[1] "env0" +[1] ".__C__Foo17R5" ".__global__" ".requireCachedGenerics" -Slot "age": -[1] 31 +##com.oracle.truffle.r.test.S4.TestR5.testAllocation# +#{ DummyClass0 <- setRefClass('DummyClass0'); DummyClass0$new() } +Reference class object of class "DummyClass0" +##com.oracle.truffle.r.test.S4.TestR5.testAllocation# +#{ DummyClass1 <- setRefClass('DummyClass1'); is(DummyClass1, 'refClass') } +[1] TRUE -##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests# -#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation10.R") } -Error in validObject(hadley) : - invalid class “Person” object: Age is length 10. Should be 1 +##com.oracle.truffle.r.test.S4.TestR5.testAllocation# +#{ DummyClass2 <- setRefClass('DummyClass2'); obj <- DummyClass2$new(); is(obj, 'refObject') } +[1] TRUE -##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests# -#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation2.R") } -Error in validObject(.Object) : - invalid class “Person” object: invalid object for slot "age" in class "Person": got class "character", should be or extend class "numeric" +##com.oracle.truffle.r.test.S4.TestR5.testAllocation# +#{ fooClass <- setRefClass('Foo6R5', fields = list( a = 'numeric')); fooClass$new(a = 1) } +Reference class object of class "Foo6R5" +Field "a": +[1] 1 -##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#Output.IgnoreErrorContext# -#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation3.R") } -Error in initialize(value, ...) : - invalid name for slot of class “Person”: sex +##com.oracle.truffle.r.test.S4.TestR5.testAllocation# +#{ fooClass <- setRefClass('Foo7R5', fields = list( a = 'numeric')); fooClass$new(1) } +Reference class object of class "Foo7R5" +Field "a": +numeric(0) +Warning message: +In methods::initRefFields(.Object, classDef, selfEnv, list(...)) : + unnamed arguments to $new() must be objects from a reference class; got an object of class “numeric” + +##com.oracle.truffle.r.test.S4.TestR5.testAllocation# +#{ setRefClass('Foo16R5'); ls(topenv(parent.frame()), all.names = T) } +[1] ".__C__Foo16R5" ".__global__" ".requireCachedGenerics" + +##com.oracle.truffle.r.test.S4.TestR5.testAttributes# +#{ clazz <- setRefClass('Foo13R5'); clazz$methods() } + [1] ".objectPackage" ".objectParent" "callSuper" "copy" + [5] "export" "field" "getClass" "getRefClass" + [9] "import" "initFields" "show" "trace" +[13] "untrace" "usingMethods" + +##com.oracle.truffle.r.test.S4.TestR5.testCheckedAssign# +#clazz <- setRefClass('Foo10R5', fields = list(a = 'numeric')); obj <- clazz$new(); obj$a <- 10; obj$a; obj$a <- 'hello'; obj$a +[1] 10 +Error: invalid assignment for reference class field ‘a’, should be from class “numeric” or a subclass (was class “character”) + +##com.oracle.truffle.r.test.S4.TestR5.testCheckedAssign# +#clazz <- setRefClass('Foo11R5', fields = list(a = 'character')); obj <- clazz$new(); obj$a <- 'hello'; obj$a; obj$a <- 10; obj$a +[1] "hello" +Error: invalid assignment for reference class field ‘a’, should be from class “character” or a subclass (was class “numeric”) + +##com.oracle.truffle.r.test.S4.TestR5.testCheckedAssign# +#clazz <- setRefClass('Foo8R5', fields = list(a = 'numeric')); obj <- clazz$new(); bindingIsActive('a', as.environment(obj)) +[1] TRUE + +##com.oracle.truffle.r.test.S4.TestR5.testCheckedAssign# +#clazz <- setRefClass('Foo9R5', fields = list(a = 'numeric')); obj <- clazz$new(); bindingIsActive('a', as.environment(obj)); obj$a <- 123; bindingIsActive('a', as.environment(obj)) +[1] TRUE +[1] TRUE + +##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#Ignored.OutputFormatting# +#print(suppressMessages({clazz <- setRefClass('Foo20R5', methods = list(foo = function() NULL)); clazz$methods('foo')})) +function() NULL +attr(,"mayCall") +character(0) +attr(,"name") +[1] "foo" +attr(,"refClassName") +[1] "Foo20R5" +attr(,"superClassMethod") +[1] "" +attr(,"class") +[1] "refMethodDef" +attr(,"class")attr(,"package") +[1] "methods" + +##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess# +#print(suppressMessages({clazz <- setRefClass('Foo21R5', methods = list(foo = function() NULL)); clazz$new()$foo(); clazz$methods(foo = function(x) x); clazz$new()$foo(3)})) +[1] 3 + +##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess# +#{ clazz <- setRefClass('Foo14R5'); obj <- clazz$new(); obj$inexistingMethod() } +Error in envRefInferField(x, what, getClass(class(x)), selfEnv) : + ‘inexistingMethod’ is not a valid field or method name for reference class “Foo14R5” + +##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess# +#{ clazz <- setRefClass('Foo14R5', fields = c('a')); obj <- clazz$new(); obj$a } +An object of class "uninitializedField" +Slot "field": +[1] "a" + +Slot "className": +[1] "ANY" + + +##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess# +#{ clazz <- setRefClass('Foo14R5', fields = c('a')); obj <- clazz$new(a = 1); print(obj$a); obj$a <- 'hello'; print(obj$a) } +[1] 1 +[1] "hello" + +##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess# +#{ clazz <- setRefClass('Foo19R5'); clazz$methods('inexistingMethod') } +NULL +Warning message: +In .getMethodDefs(methodDefs[[1]], methodsEnv) : + Methods not found: “.objectPackage”, “.objectParent”, “callSuper”, “copy”, “export”, “field”, “getClass”, “getRefClass”, “import”, “initFields”, “show”, “trace”, “untrace”, “usingMethods” + +##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess# +#{ clazz <- setRefClass('Foo22R5'); clazz$fields() } +NULL + +##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess# +#{ clazz <- setRefClass('Foo23R5', fields = c('a', 'b', 'c')); clazz$fields() } + a b c +"ANY" "ANY" "ANY" + +##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess# +#{ clazz <- setRefClass('Foo24R5', fields = list(a = 'numeric')); clazz$fields() } + a +"numeric" + +##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess# +#{ clazz <- setRefClass('Foo25R5', fields = list(a = 'numeric', b = 'character', c = 'raw')); clazz$fields() } + a b c + "numeric" "character" "raw" + +##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess# +#{ clazz <- setRefClass('Foo26R5', fields = list(a = 'numeric')); clazz$lock('a'); obj <- clazz$new(); obj$a <- 10; obj$a } +[1] 10 + +##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess# +#{ clazz <- setRefClass('Foo27R5', fields = list(a = 'numeric')); clazz$lock('a'); obj <- clazz$new(); obj$a <- 10; obj$a <- 20 } +Error: invalid replacement: reference class field ‘a’ is read-only + +##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#Output.ImprovedErrorContext# +#{ clazz <- setRefClass('Foo28R5', fields = list(a = 'numeric', b = 'character')); clazz$accessors(); clazz$methods() } +Error in `substr<-`(`*tmp*`, 1, 1, value = character(0)) : + replacing substrings in a non-character object + +##com.oracle.truffle.r.test.S4.TestR5.testInheritance# +#A0R5 <- setRefClass('A0R5', field = list(a = 'numeric')); B0R5 <- setRefClass('B0R5', contains = 'A0R5'); obj <- B0R5$new(a = 1); obj$a +[1] 1 + +##com.oracle.truffle.r.test.S4.TestR5.testInheritance# +#A5R5 <- setRefClass('A5R5', field = c('a'), methods = list(initialize <- function() { a <<- 0 })); B5R5 <- setRefClass('B5R5', field = c('a'), methods = list(initialize <- function() { a <<- 'hello' })); C5R5 <- setRefClass('C5R5', contains = c('A5R5', 'B5R5')); obj <- C5R5$new(); obj$a <- raw(0) + +##com.oracle.truffle.r.test.S4.TestR5.testInheritance# +#print(suppressMessages({A1R5 <- setRefClass('A1R5', methods = list(foo = function() { print('hello') })); B1R5 <- setRefClass('B1R5', contains = 'A1R5'); obj <- B1R5$new(); obj$foo()})) +[1] "hello" +[1] "hello" + +##com.oracle.truffle.r.test.S4.TestR5.testInheritance# +#print(suppressMessages({A2R5 <- setRefClass('A2R5', methods = list(foo = function() { print('hello') })); B2R5 <- setRefClass('B2R5', methods = list(foo = function() { print('world') }), contains = 'A2R5'); obj <- B2R5$new(); obj$foo()})) +[1] "world" +[1] "world" + +##com.oracle.truffle.r.test.S4.TestR5.testInheritance# +#print(suppressMessages({A3R5 <- setRefClass('A3R5', methods = list(foo = function() { print('hello') })); B3R5 <- setRefClass('B3R5', methods = list(foo = function() { callSuper(); print('world') }), contains = 'A3R5'); obj <- B3R5$new(); obj$foo()})) +[1] "hello" +[1] "world" +[1] "world" + +##com.oracle.truffle.r.test.S4.TestR5.testInheritance#Ignored.OutputFormatting# +#print(suppressMessages({{ setRefClass('A4R5', fields = c('a')); setRefClass('B4R5', contains = 'A4R5', methods = list(set_a = function(a){ a <<- a })) }})) +function (...) +new("B4R5", ...) +attr(,"className") +[1] "B4R5" +attr(,"className")attr(,"package") +[1] ".GlobalEnv" +attr(,"package") +[1] ".GlobalEnv" +attr(,"generator") +Reference class object of class "refGeneratorSlot" +Field "def": +Reference Class "B4R5": + +Class fields: + +Name: a +Class: ANY + +Class Methods: + "set_a", "import", ".objectParent", "usingMethods", "show", "getClass", + "untrace", "export", ".objectPackage", "callSuper", "copy", "initFields", + "getRefClass", "trace", "field" + +Reference Superclasses: + "A4R5", "envRefClass" + +Field "className": +[1] "B4R5" +attr(,"class") +[1] "refObjectGenerator" +attr(,"class")attr(,"package") +[1] "methods" + +##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods# +#clazz <- setRefClass('Foo2R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); obj$field('a'); obj$field('b') +[1] 1 +[1] 5 + +##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods# +#clazz <- setRefClass('Foo3R5', c('a', 'b')); obj <- clazz$new(); obj$initFields(a = 5, b = 6) +Reference class object of class "Foo3R5" +Field "a": +[1] 5 +Field "b": +[1] 6 + +##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods# +#print(suppressMessages({{ clazz <- setRefClass('Foo0R5', c('a', 'b')); clazz$methods(mean = function() { (a + b) / 2 }); obj <- clazz$new(a = 1, b = 5); obj$mean() }})) +[1] 3 + +##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods# +#print(suppressMessages({{ clazz <- setRefClass('Foo12R5', fields = list(a = 'numeric'), methods = list(inc = function() { a <<- a+1 })); obj <- clazz$new(a = 0); obj$inc(); obj$a }})) +[1] 1 + +##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods# +#print(suppressMessages({{ clazz <- setRefClass('Foo15R5', fields = c('a'), methods = list(initialize = function() { a <<- 123 })); obj <- clazz$new(); obj$a }})) +[1] 123 + +##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods# +#print(suppressMessages({{ clazz <- setRefClass('Foo28R5', fields = list(a = 'numeric'), methods = list(inc = function() { a <<- a+1 })); obj <- clazz$new(a = 0); obj$inc(); obj$a }})) +[1] 1 + +##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods# +#print(suppressMessages({{ setRefClass('A6R5', fields = c('a'), methods = list(initialize = function() { a <<- 'hello' })); clazz <- setRefClass('B6R5', fields = c('a'), contains = 'A6R5'); obj <- clazz$new(); obj$a }})) +[1] "hello" + +##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods# +#{ clazz <- setRefClass('Foo13R5'); obj <- clazz$new(); obj$inexistingMethod() } +Error in envRefInferField(x, what, getClass(class(x)), selfEnv) : + ‘inexistingMethod’ is not a valid field or method name for reference class “Foo13R5” + +##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#Ignored.Unknown# +#{ clazz <- setRefClass('Foo18R5', fields = c('a'), methods = list(initialize = function() a <<- 456, finalize = function() { print(sprintf('finalizer: %d', a)) } )); (function () { x <- clazz$new(); print('fun') })(); gc() } +code for methods in class “Foo18R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?) +[1] "fun" +[1] "finalizer: 456" + used (Mb) gc trigger (Mb) max used (Mb) +Ncells 247442 13.3 460000 24.6 350000 18.7 +Vcells 455966 3.5 1023718 7.9 784463 6.0 + +##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods# +#{ clazz <- setRefClass('Foo1R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); cobj <- obj$copy(); obj$a; cobj$a; obj$a <- 10; obj$a; cobj$a} +[1] 1 + +##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#Output.IgnoreErrorContext# +#{ clazz <- setRefClass('Foo4R5', c('a', 'b')); clazz$accessors() } +Error in `substr<-`(`*tmp*`, 1, 1, value = character(0)) : + replacing substrings in a non-character object + +##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods# +#{ clazz <- setRefClass('Foo5R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); attributes(obj$getRefClass())$className } +[1] "Foo5R5" +attr(,"package") +[1] ".GlobalEnv" + +##com.oracle.truffle.r.test.S4.TestR5.testReferenceSemantics# +#fooClass <- setRefClass('Foo12R5', fields = list( a = 'numeric')); obj0 <- fooClass$new(a = 1); obj1 <- obj0; obj0$a; obj1$a; obj0$a <- 999; obj0$a; obj1$a +[1] 1 +[1] 1 +[1] 999 +[1] 999 ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests# -#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation4.R") } -numeric(0) +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/NextMethod.R") } +foo.bar(A, D) +foo.bar(C, D) ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests# -#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation5.R") } -numeric(0) +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/NextMethod1.R") } +foo.bar(A, D) +foo.bar(B, D) +foo.bar(A, D) +foo.bar(C, D) +foo.bar(C, E) +foo.bar(A, D) +foo.bar(B, D) ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests# -#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation6.R") } -[1] NA +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/activeBinding0.R") } +get +[1] 1 +set +get +[1] 2 ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests# -#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation7.R") } -Error in validObject(.Object) : - invalid class “Person” object: Age is length 0. Should be 1 +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/activeBinding1.R") } +get +1 +##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests# +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/activeBinding2.R") } ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests# -#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation8.R") } -Error in validObject(.Object) : - invalid class “Person” object: Age is length 10. Should be 1 +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/activeBinding3.R") } +set +get +[1] 3 ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests# -#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation9.R") } -An object of class "Person" -Slot "name": -[1] "Hadley" +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/dispatch.R") } +Creating a generic function from function ‘foo.bar’ in the global environment +[1] 1 +[1] 2 +[1] 3 +[1] "primitive, A, B" +[1] "primitive, B, A" -Slot "age": -[1] 31 +##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#Output.IgnoreErrorContext# +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/refClasses0.R") } +Error : invalid assignment for reference class field ‘aa’, should be from class “integer” or a subclass (was class “character”) +code for methods in class “myRefClass3” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?) +Error : invalid assignment for reference class field ‘dd’, should be from class “numeric” or a subclass (was class “character”) +code for methods in class “myRefClass4” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?) +code for methods in class “myRefClass5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?) +code for methods in class “myRefClass6” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?) +##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests# +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/refClasses1.R") } +code for methods in class “A5R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?) +code for methods in class “B5R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?) +[1] "A5R5$foo" ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests# -#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/methods1.R") } -Function: sides (package .GlobalEnv) -object="Polygon" -object="Square" -object="Triangle" +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/refClasses2.R") } +code for methods in class “MatrixClass” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?) + +##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings# +#.Internal(bindingIsActive(as.name('someSymbol4'), .GlobalEnv)) +Error: no binding for "someSymbol4" + +##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings# +#bindingIsActive('someSymbol3', .GlobalEnv) +Error in bindingIsActive("someSymbol3", .GlobalEnv) : + no binding for "someSymbol3" + +##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings#Output.IgnoreErrorContext# +#lockEnvironment(.GlobalEnv); makeActiveBinding('someSymbol1', function(x) { x }, .GlobalEnv) +Error in makeActiveBinding("someSymbol1", function(x) { : + cannot add bindings to a locked environment +Error during wrapup: cannot add bindings to a locked environment + +##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings# +#makeActiveBinding('someSymbol10', function(x) { if(missing(x)) print('get0') else print('set0'); NULL }, .GlobalEnv); someSymbol10; someSymbol10 <- 1; makeActiveBinding('someSymbol10', function(x) { if(missing(x)) print('get1') else print('set1'); NULL }, .GlobalEnv); someSymbol10; someSymbol10 <- 1 +[1] "get0" +NULL +[1] "set0" +[1] "get1" +NULL +[1] "set1" -description class mode text opened can read - "stdout" "terminal" "w" "text" "opened" "no" - can write - "yes" -description class mode text opened can read - "stdout" "terminal" "w" "text" "opened" "no" - can write - "yes" +##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings# +#makeActiveBinding('someSymbol2', function(x) { x }, .GlobalEnv); bindingIsActive('someSymbol2', .GlobalEnv) +[1] TRUE -##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests# -#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/methods2.R") } -Function: sides (package .GlobalEnv) -object="Polygon" +##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings# +#makeActiveBinding('someSymbol6', function(x) { x }, .GlobalEnv); lockBinding('someSymbol6', .GlobalEnv); makeActiveBinding('someSymbol6', function(x) { print('hello') }, .GlobalEnv) +Error in makeActiveBinding("someSymbol6", function(x) { : + cannot change active binding if binding is locked -description class mode text opened can read - "stdout" "terminal" "w" "text" "opened" "no" - can write - "yes" -description class mode text opened can read - "stdout" "terminal" "w" "text" "opened" "no" - can write - "yes" +##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings#Ignored.Unknown# +#makeActiveBinding('someSymbol7', function(x) { if(missing(x)) print('get0') else print('set0') }, .GlobalEnv); someSymbol7; someSymbol7 <- 1; makeActiveBinding('someSymbol7', function(x) { if(missing(x)) print('get1') else print('set1') }, .GlobalEnv); someSymbol7; someSymbol7 <- 1 +[1] "get0" +[1] "set0" +[1] "get1" +[1] "set1" -##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests# -#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/methods3.R") } -Error in .valueClassTest(ans, "numeric", "sides") : - invalid value from generic function ‘sides’, class “character”, expected “numeric” +##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings# +#makeActiveBinding('someSymbol8', function(x) { print('hello') }, .GlobalEnv); someSymbol9 <- 'world'; print(someSymbol8); print(someSymbol9) +[1] "hello" +[1] "hello" +[1] "world" -##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests# -#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/methods4.R") } -Note: method with signature ‘A2#A1’ chosen for function ‘foo’, - target signature ‘A2#A2’. - "A1#A2" would also be valid -[1] "2-1" -[1] "2-1" +##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings# +#makeActiveBinding('var_a', function(x) { if(missing(x)) { print('get'); return(123) } else { print('set'); return(x) } }, .GlobalEnv); inherits(var_a, 'numeric') +[1] "get" +[1] TRUE -##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests# -#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/methods5.R") } -[1] "Looking for rust" -character(0) -[1] "Checking seat belts" +##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings# +#someSymbol0 <- 1; makeActiveBinding('someSymbol0', function(x) { x }, .GlobalEnv) +Error in makeActiveBinding("someSymbol0", function(x) { : + symbol already has a regular binding -##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests# -#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/slot_access1.R") } - name age -"character" "numeric" +##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings# +#someSymbol5 <- 0; lockBinding('someSymbol5', .GlobalEnv); makeActiveBinding('someSymbol5', function(x) { x }, .GlobalEnv) +Error in makeActiveBinding("someSymbol5", function(x) { : + symbol already has a regular binding ##com.oracle.truffle.r.test.S4.TestS4.testAllocation# #{ new("numeric") } numeric(0) +##com.oracle.truffle.r.test.S4.TestS4.testAllocation#Output.IgnoreErrorContext# +#{ setClass("foo", representation(j="numeric")); new("foo", inexisting=42) } +Error in initialize(value, ...) : + invalid name for slot of class “foo”: inexisting + +##com.oracle.truffle.r.test.S4.TestS4.testAllocation# +#{ setClass("foo", representation(j="numeric")); new("foo", j='text') } +Error in validObject(.Object) : + invalid class “foo” object: invalid object for slot "j" in class "foo": got class "character", should be or extend class "numeric" + ##com.oracle.truffle.r.test.S4.TestS4.testAllocation# #{ setClass("foo", representation(j="numeric")); new("foo", j=42) } An object of class "foo" @@ -120,15 +412,11 @@ Slot "j": [1] 42 -##com.oracle.truffle.r.test.S4.TestS4.testAllocation# -#{ setClass("foo", representation(j="numeric")); typeof(new("foo", j=42)) } -[1] "S4" - ##com.oracle.truffle.r.test.S4.TestS4.testClassCreation# #{ setClass("foo"); setClass("bar", representation(j = "numeric"), contains = "foo"); is.null(getClass("foo")@prototype) } [1] FALSE -##com.oracle.truffle.r.test.S4.TestS4.testClassCreation#Ignored.OutputFormatting# +##com.oracle.truffle.r.test.S4.TestS4.testClassCreation# #{ setClass("foo", representation(j="numeric")); getClass("foo") } Class "foo" [in ".GlobalEnv"] @@ -137,6 +425,26 @@ Slots: Name: j Class: numeric +##com.oracle.truffle.r.test.S4.TestS4.testClassCreation# +#{ setClass('foo', contains='standardGeneric'); getClass('foo') } +Class "foo" [in ".GlobalEnv"] + +Slots: + +Name: .Data generic package group +Class: function character character list + +Name: valueClass signature default skeleton +Class: character character optionalMethod call + +Extends: +Class "standardGeneric", directly +Class "genericFunction", by class "standardGeneric", distance 2 +Class "function", by class "standardGeneric", distance 3 +Class "OptionalFunction", by class "standardGeneric", distance 4 +Class "PossibleMethod", by class "standardGeneric", distance 4 +Class "optionalMethod", by class "standardGeneric", distance 5 + ##com.oracle.truffle.r.test.S4.TestS4.testConversions# #{ asS4(7:42) } [1] 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 @@ -158,11 +466,21 @@ Class: numeric #{ x<-42; y<-asS4(x); isS4(y) } [1] TRUE +##com.oracle.truffle.r.test.S4.TestS4.testInternalDispatch# +#setClass('foo', representation(d='numeric')); setMethod(`$`, signature('foo'), function(x, name) 'FOO'); obj <- new('foo'); obj$asdf +[1] "$" +[1] "FOO" + +##com.oracle.truffle.r.test.S4.TestS4.testMethods# +#setGeneric('do.call', signature = c('what', 'args')) +Creating a new generic function for ‘do.call’ in the global environment +[1] "do.call" + ##com.oracle.truffle.r.test.S4.TestS4.testMethods#Ignored.OutputFormatting# #{ gen<-function(object) 0; setGeneric("gen"); res<-print(gen); removeGeneric("gen"); res } function (object) standardGeneric("gen") -<environment: 0x7fe323e45660> +<environment: 0x2983900> attr(,"generic") [1] "gen" attr(,"generic")attr(,"package") @@ -196,7 +514,7 @@ standardGeneric for "gen" defined from package ".GlobalEnv" function (object) standardGeneric("gen") -<environment: 0x7fe323e45660> +<environment: 0x2983900> Methods may be defined for arguments: object Use showMethods("gen") for currently available ones. @@ -215,6 +533,22 @@ Creating a generic function for ‘diag<-’ from package ‘base’ in the glob [1] "FOO" "BAR" [1] "FOO" "BAR" +##com.oracle.truffle.r.test.S4.TestS4.testMethods# +#{ setClass('A'); setClass('A1', contains = 'A'); setClass('A2', contains = 'A1'); setGeneric('foo', function(a, b) standardGeneric('foo')); setMethod('foo', signature('A1', 'A2'), function(a, b) '1-2'); setMethod('foo', signature('A2', 'A1'), function(a, b) '2-1'); foo(new('A2'), new('A2')) } +Note: method with signature ‘A2#A1’ chosen for function ‘foo’, + target signature ‘A2#A2’. + "A1#A2" would also be valid +[1] "2-1" + +##com.oracle.truffle.r.test.S4.TestS4.testMethods# +#{ setClass('A1', representation(a='numeric')); setMethod('length', 'A1', function(x) x@a); obj <- new('A1'); obj@a <- 10; length(obj) } +[1] 10 + +##com.oracle.truffle.r.test.S4.TestS4.testMethods# +#{ setClass('A2', representation(a = 'numeric')); setMethod('rep', 'A2', function(x, a, b, c) { c(x@a, a, b, c) }); setMethod('ifelse', c(yes = 'A2'), function(test, yes, no) print(test)) } +Creating a generic function for ‘ifelse’ from package ‘base’ in the global environment +[1] "ifelse" + ##com.oracle.truffle.r.test.S4.TestS4.testMethods# #{ setGeneric("gen", function(o) standardGeneric("gen")); res<-print(setGeneric("gen", function(o) standardGeneric("gen"))); removeGeneric("gen"); res } [1] "gen" @@ -223,7 +557,7 @@ Creating a generic function for ‘diag<-’ from package ‘base’ in the glob ##com.oracle.truffle.r.test.S4.TestS4.testMethods#Ignored.OutputFormatting# #{ setGeneric("gen", function(object) standardGeneric("gen")); res<-print(gen); removeGeneric("gen"); res } function(object) standardGeneric("gen") -<environment: 0x7fba68bbb3c0> +<environment: 0x11f3000> attr(,"generic") [1] "gen" attr(,"generic")attr(,"package") @@ -250,10 +584,25 @@ standardGeneric for "gen" defined from package ".GlobalEnv" function (object) standardGeneric("gen") -<environment: 0x7fba68bbb3c0> +<environment: 0x11f3000> Methods may be defined for arguments: object Use showMethods("gen") for currently available ones. +##com.oracle.truffle.r.test.S4.TestS4.testObjectValidity# +#{ check <- function(object) length(object@n) == 1; setClass('SingleInt', representation(n = 'numeric'), validity = check); new('SingleInt', n = 1) } +An object of class "SingleInt" +Slot "n": +[1] 1 + + +##com.oracle.truffle.r.test.S4.TestS4.testObjectValidity# +#{ check <- function(object) length(object@n) == 1; setClass('SingleInt', representation(n = 'numeric'), validity = check); new('SingleInt', n = c(1, 2)) } +Error in validObject(.Object) : invalid class “SingleInt” object: FALSE + +##com.oracle.truffle.r.test.S4.TestS4.testObjectValueSemantics# +#{ setClass('WrappedIntVec', representation(n = 'numeric')); x0 <- new('WrappedIntVec', n = 1); x1 <- x0; x1@n <- 2; x0@n == x1@n } +[1] FALSE + ##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#Output.IgnoreErrorContext# # { x<-42; attr(x, "foo")<-7; x@foo } Error: trying to get slot "foo" from an object of a basic class ("numeric") with no slots @@ -300,6 +649,23 @@ numeric(0) #{ setClass("foo", contains="numeric"); x<-new("foo"); res<-x@.Data; removeClass("foo"); res } numeric(0) +##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess# +#{ setClass('A0', representation(name = 'character', age = 'numeric')); getSlots('A0') } + name age +"character" "numeric" + +##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess# +#{ setClass('A1', representation(name = 'character', age = 'numeric'), prototype(name = NA_character_, age = NA_real_)); obj <- new('A1', name = 'FastR'); obj@age } +[1] NA + +##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess# +#{ setClass('A2', representation(name = 'character', age = 'numeric')); obj <- new('A2', name = 'FastR'); obj@age } +numeric(0) + +##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess# +#{ setClass('A3', representation(name = 'character', age = 'numeric')); obj <- new('A3', name = 'FastR'); slot(obj, 'age') <- 5; obj@age } +[1] 5 + ##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess# #{ x<-42; `@`(x, ".Data") } [1] 42 @@ -359,13 +725,14 @@ Error in (function (cl, name, valueClass) : Error in slot(y, "foo") <- 42 : object 'y' not found ##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#Output.IgnoreErrorContext# -#{ x<-function() 42; attr(x, "foo")<-7; y<-asS4(x); y@foo<-42 } +#{ x<-function() 42; attr(x, "foo")<-7; x@foo<-42 } Error in (function (cl, name, valueClass) : ‘foo’ is not a slot in class “function” ##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#Output.IgnoreErrorContext# -#{ x<-function() 42; attr(x, "foo")<-7; y@foo<-42 } -Error in y@foo <- 42 : object 'y' not found +#{ x<-function() 42; attr(x, "foo")<-7; y<-asS4(x); y@foo<-42 } +Error in (function (cl, name, valueClass) : + ‘foo’ is not a slot in class “function” ##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate# #{ x<-getClass("ClassUnionRepresentation"); slot(x, "virtual", check=TRUE)<-TRUE; x@virtual } @@ -378,12 +745,16 @@ Error in y@foo <- 42 : object 'y' not found ##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate# #{ x<-initialize@valueClass; initialize@valueClass<-"foo"; initialize@valueClass<-x } +##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric# +#{ setClass('A4', representation(a = 'numeric')); setMethod('[[', 'A4', function(x, i, j, ...) NULL); obj <- new('A4'); obj[[1]] } +NULL + ##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric# #{ standardGeneric("") } Error in standardGeneric("") : argument to 'standardGeneric' must be a non-empty character string -##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric# +##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#Output.IgnoreErrorContext# #{ standardGeneric("foo", 42) } Error: expected a generic function or a primitive for dispatch, got an object of class "numeric" @@ -397,7 +768,7 @@ Error in standardGeneric(42) : Error in standardGeneric(character()) : argument to 'standardGeneric' must be a non-empty character string -##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric# +##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#Output.IgnoreErrorContext# #{ x<-42; class(x)<-character(); standardGeneric("foo", x) } Error: expected a generic function or a primitive for dispatch, got an object of class "numeric" @@ -546,6 +917,35 @@ Error in Conj(as.raw(12)) : non-numeric argument to function attr(,"foo") [1] "foo" +##com.oracle.truffle.r.test.builtins.TestBuiltin_D.testD# +#(df <- D(1, "x"));df(0) +[1] 0 +Error in df(0) : argument "df1" is missing, with no default + +##com.oracle.truffle.r.test.builtins.TestBuiltin_D.testD# +#(df <- D(expression(x^2*sin(x)), "x"));df(0) +2 * x * sin(x) + x^2 * cos(x) +Error in df(0) : argument "df1" is missing, with no default + +##com.oracle.truffle.r.test.builtins.TestBuiltin_D.testD# +#(df <- D(quote(x^2*sin(x)), "x"));df(0) +2 * x * sin(x) + x^2 * cos(x) +Error in df(0) : argument "df1" is missing, with no default + +##com.oracle.truffle.r.test.builtins.TestBuiltin_D.testD# +#D(expression(), 'a') +[1] NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_D.testD# +#g<-quote(x^2);(df <- D(g, "x"));df(0) +2 * x +Error in df(0) : argument "df1" is missing, with no default + +##com.oracle.truffle.r.test.builtins.TestBuiltin_D.testD# +#x<-1;(df <- D(x, "x"));df(0) +[1] 0 +Error in df(0) : argument "df1" is missing, with no default + ##com.oracle.truffle.r.test.builtins.TestBuiltin_Date2POSIXlt.testDate2POSIXlt1# #argv <- list(structure(c(14712, 14712), class = 'Date')); .Internal(Date2POSIXlt(argv[[1]])) [1] "2010-04-13 UTC" "2010-04-13 UTC" @@ -941,7 +1341,7 @@ $vt [1,] 0 -##com.oracle.truffle.r.test.builtins.TestBuiltin_La.testLa9#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_La.testLa9# #argv <- list(structure(c(-9.64365076099295, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, -29634.0055320061, -5658.08855789941, 0.0595010632288954, 0.0648032071760975, 0.106336668095848, -0.0279843118999398, 0.0762911857283688, 0.188519899277481, 0.0807096390177039, 0.102801905464379, 0.158474416910002, -0.0969121832135675, -0.0447744343994132, 0.0356414154664858, 0.0276881995456826, -5.08106330417909, 3.14280306547868, 3.64768208463163, 0.0962151262827947, -0.216651778533863, -0.0914289830351174, 0.0855052819309283, -0.0191216590449975, 0.0813861110263642, 0.0607902565035442, 0.00888870310603775, -0.027169916923919, -0.0757761335977742, 0.123401654252917, -0.143330536432624, -0.207390338946085, -0.18719988871654, -0.127596387499216, 1.38045811630541, 0.0118370110620473, 0.00504893180870276, 0.0281684584122627, 0.0338400772620966, 0.0283917504929648, 0.0295082108964754, 0.0323216911133222, 0.00156557534974961, 0.00420042190203468, 0.0261141712698031, 0.00786241202554953, -3.21455025366432, -2.66432733346907, -2.18217405946767, -1.0459324747522, 2.77707906967759, -0.000588115022584812, -0.0784367740030637, -0.0437014732535189, -0.0770692424774911, 0.28985899050302, 0.307089887725235, -0.0219216068215179, -0.00578473481976082, -0.0910180640383319, 0.0166427821996303, -0.725866186311298, -0.943724610301472, -0.197997366006898, -0.255325765345392, -1.99736582726463, 1.22009740929232, -0.000660179745382102, 0.118090770461339, 0.00401505451472504, -0.265276591063721, -0.206368639386371, -0.0413572976755921, 0.0138104665936721, -0.0436723349383677, 0.0904843084594291, -0.103695169473043, 0.0314422837299137, -0.171533212490836, -0.0271695331685966, -0.234884785308008, -0.455412006973628, -0.833981960018826, -0.0497205266764892, -0.00169048456815939, 0.0359873442560765, 0.0111849454624309, 0.0174129325629219, -0.00581471075176227, 0.0183876477886015, -0.0380971980704758, -1.14064686420347, -1.21031412747477, -0.546078284372325, -0.385964209884133, -0.535335872363138, 0.617909299639904, 0.034437791264286, -2.66782912116871, -0.0707120154460491, 0.170259689757997, -0.200116024334743, -0.0120487035676503, -0.00787104751465206, -0.0743232096613527, -0.00206481367828156, -2.28129372840694, -1.27183039972242, -0.162921372163874, 0.194143545128708, 0.405329624202872, -0.0239884453210967, 0.161826508366356, 1.47283157923894, -3.57122150532158, 0.0184573285734211, 0.0768346205272587, -0.00300367200170235, -0.047539037475449, -0.0955077077363865, 0.170580587807138, -2.17759855893389, 2.82091161681306, -0.529126651121425, 0.00648102843720064, -0.227590137804697, 0.429332016819553, 0.315382802791974, -0.0921680424483324, 0.358484158960907, 2.74734594573339, -0.00180797874108619, 0.211048746835586, 0.146553774483952, 0.0892496085418831, 0.02104367339158, -1.4517323726226, 0.428703993666521, -0.198393471445493, -0.178300389025286, -0.0518091667043893, 0.133208332446864, -1.01393441911662, 0.520772381447608, 0.936102434059857, -1.6420319436063, 2.59716822825227, 0.194828402482676, 0.15057424104202, -0.232155536267878, -0.0298159890277092, -0.933256525257383, -1.20515451427884, 0.0125087156504907, 0.421920000319943, 0.452875082015975, -0.655679104390575, 0.284781968418535, 0.643096539054797, 1.38165893036928, 0.447700892848835, -0.482856979100538, 1.73960015308741, 0.115853953901054, 0.107343556163412, -0.0385322695831968, -25.7267715462619, -8.40853040573162, -1.45105839286435, -1.58984152452525, -1.59606771970776, 2.79428919380473, 0.596892611732863, -1.03839368638655, -0.0376487500979583, -0.507302835476536, 0.184174590388395, -0.70905481454677, -3.32884312972433, 0.134236291836065, -0.0993249017707237, -6.94757635469386, 1.58613921242054, 0.195741168102286, 0.638223445194413, 1.07571321411184, 0.659104584950073, 0.199707908602043, -0.565980943574209, -0.967985377031296, -0.112927393875596, -0.934672543429794, 0.198159847509218, 0.275086401661377, 3.44668029704689, -0.05066048099299, -1.65912271156868, -1.17593571026872, -0.20132598039105, -0.42732880950559, -1.20727437557593, 0.102943259109259, -0.697974199306205, 0.103630431164098, -0.0620963660266192, -0.16978912837867, 0.739571733406047, -0.872308493604205, -0.757980967070979, -2.00985526447536, -1.92891236077264), .Dim = c(15L, 15L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15'), c('(Intercept)', 'Weight', 'Cylinders4', 'Cylinders5', 'Cylinders6', 'Cylinders8', 'Cylindersrotary', 'TypeLarge', 'TypeMidsize', 'TypeSmall', 'TypeSporty', 'TypeVan', 'EngineSize', 'DriveTrainFront', 'DriveTrainRear'))), 15L); .Internal(La_chol2inv(argv[[1]], argv[[2]])) [,1] [,2] [,3] [,4] [,5] [1,] 2.4965590071 -8.201566e-04 0.0523016012 0.4022192142 0.3409468314 @@ -1366,6 +1766,34 @@ Error in Recall(10) : 'Recall' called from outside a closure #argv <- structure(list(f = function(f, ...) f(...), x = list(.Primitive('log'), .Primitive('exp'), .Primitive('acos'), .Primitive('cos')), init = 0, right = TRUE), .Names = c('f', 'x', 'init', 'right'));do.call('Reduce', argv) [1] 0 +##com.oracle.truffle.r.test.builtins.TestBuiltin_SplineCoef.testNull# +#.Call(stats:::C_SplineCoef, 0, 0, NULL) +Error: inputs of different lengths + +##com.oracle.truffle.r.test.builtins.TestBuiltin_SplineCoef.testSimple# +#.Call(stats:::C_SplineCoef, 0, 0, 0) +$method +[1] 0 + +$n +[1] 1 + +$x +[1] 0 + +$y +[1] 0 + +$b +[1] 0 + +$c +[1] 0 + +$d +[1] 0 + + ##com.oracle.truffle.r.test.builtins.TestBuiltin_Syschmod.testSyschmod1#Ignored.SideEffects# #argv <- list(character(0), structure(integer(0), class = 'octmode'), TRUE); .Internal(Sys.chmod(argv[[1]], argv[[2]], argv[[3]])) @@ -1432,11 +1860,11 @@ Error: invalid 'category' argument In addition: Warning message: NAs introduced by coercion -##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocaleInvalidArgs#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocaleInvalidArgs# #.Internal(Sys.setlocale(4, 42)) Error: invalid 'locale' argument -##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocaleInvalidArgs#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocaleInvalidArgs# #.Internal(Sys.setlocale(4, c('more', 'elements'))) Error: invalid 'locale' argument @@ -1773,7 +2201,7 @@ Frequency = 1 [6] 1.000000000 0.000000000 1.957854406 48.498545455 Inf [11] 1.000000000 1.000000000 0.342969777 0.007071754 -##com.oracle.truffle.r.test.builtins.TestBuiltin_abs.testabs4#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_abs.testabs4# #argv <- list(c(0, 0, 0, 0, 0, 1.75368801162502e-134, 0, 0, 0, 2.60477585273833e-251, 1.16485035372295e-260, 0, 1.53160350210786e-322, 0.333331382328728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.44161262707711e-123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.968811545398e-173, 0, 8.2359965384697e-150, 0, 0, 0, 0, 6.51733217171341e-10, 0, 2.36840184577368e-67, 0, 9.4348408357524e-307, 0, 1.59959906013771e-89, 0, 8.73836857865034e-286, 7.09716190970992e-54, 0, 0, 0, 1.530425353017e-274, 8.57590058044551e-14, 0.333333106397154, 0, 0, 1.36895217898448e-199, 2.0226102635783e-177, 5.50445388209462e-42, 0, 0, 0, 0, 1.07846402051283e-44, 1.88605464411243e-186, 1.09156111051203e-26, 0, 3.0702877273237e-124, 0.333333209689785, 0, 0, 0, 0, 0, 0, 3.09816093866831e-94, 0, 0, 4.7522727332095e-272, 0, 0, 2.30093251441394e-06, 0, 0, 1.27082826644707e-274, 0, 0, 0, 0, 0, 0, 0, 4.5662025456054e-65, 0, 2.77995853978268e-149, 0, 0, 0));abs(argv[[1]]); [1] 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 [6] 1.753688e-134 0.000000e+00 0.000000e+00 0.000000e+00 2.604776e-251 @@ -2118,7 +2546,7 @@ In all(1) : coercing argument of type 'double' to logical #{ all(TRUE, TRUE, TRUE) } [1] TRUE -##com.oracle.truffle.r.test.builtins.TestBuiltin_all.testAll#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_all.testAll# #{ all(TRUE,c(TRUE,TRUE),1) } [1] TRUE Warning message: @@ -2178,7 +2606,7 @@ Warning messages: #argv <- list(structure(c(FALSE, FALSE), .Names = c('x', 'value')));all(argv[[1]]); [1] FALSE -##com.oracle.truffle.r.test.builtins.TestBuiltin_all.testall3#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_all.testall3# #argv <- list(c(1, 1, 3, 1, 1, 3, 3, 3, 3), FALSE, NULL);all(argv[[1]],argv[[2]],argv[[3]]); [1] FALSE Warning message: @@ -2331,6 +2759,10 @@ character(0) #{ all.names(expression(sin(x+y+x)), unique=T) } [1] "sin" "+" "x" "y" +##com.oracle.truffle.r.test.builtins.TestBuiltin_allnames.testAllNames# +#{ all.names(quote(switch(x, 'median' =, 'hello' = print('hello case')))) } +[1] "switch" "x" "print" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_allnames.testallnames1# #argv <- list(quote(y ~ ((g1) * exp((log(g2/g1)) * (1 - exp(-k * (x - Ta)))/(1 - exp(-k * (Tb - Ta)))))), FALSE, -1L, TRUE); .Internal(all.names(argv[[1]], argv[[2]], argv[[3]], argv[[4]])) [1] "y" "g1" "g2" "k" "x" "Ta" "Tb" @@ -2539,7 +2971,7 @@ In any(argv[[1]]) : coercing argument of type 'double' to logical #{ anyDuplicated(c(1,2,1)) } [1] 3 -##com.oracle.truffle.r.test.builtins.TestBuiltin_anyDuplicated.testAnyDuplicated#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_anyDuplicated.testAnyDuplicated# #{ anyDuplicated(c(1,2,3,2), incomparables = c(2+6i)) } [1] 0 Warning message: @@ -2550,7 +2982,7 @@ In anyDuplicated.default(c(1, 2, 3, 2), incomparables = c(2 + (0+6i))) : #{ anyDuplicated(c(1,2,3,4)) } [1] 0 -##com.oracle.truffle.r.test.builtins.TestBuiltin_anyDuplicated.testAnyDuplicated#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_anyDuplicated.testAnyDuplicated# #{ anyDuplicated(c(1L, 2L, 1L, 1L, 3L, 2L), incomparables = "cat") } [1] 3 Warning message: @@ -2796,7 +3228,7 @@ Error in aperm.default(array(1, c(3, 3, 3)), c(1, 2)) : Error in aperm.default(array(1, c(3, 3, 3)), c(1, 2, 0)) : value out of range in 'perm' -##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testAperm#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testAperm# #{ aperm(array(1:27,c(3,3,3)), c(1+1i,3+3i,2+2i))[1,2,3] == array(1:27,c(3,3,3))[1,3,2]; } [1] TRUE Warning message: @@ -4125,7 +4557,7 @@ Error in array(1:4, 1:2, 4) : 'dimnames' must be a list #{ array(1:4, NULL) } Error in array(1:4, NULL) : 'dims' cannot be of length 0 -##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray# #{ array(1:4, c(1+2i, 2+2i)) } [,1] [,2] [1,] 1 2 @@ -5202,6 +5634,14 @@ numeric(0) #argv <- list(structure(list(sec = 0, min = 0L, hour = 0L, mday = 22:27, mon = 3L, year = 108L, wday = 2L, yday = 112L, isdst = -1L), .Names = c('sec', 'min', 'hour', 'mday', 'mon', 'year', 'wday', 'yday', 'isdst'), class = c('POSIXlt', 'POSIXt'), tzone = 'GMT'), 'GMT'); .Internal(as.POSIXct(argv[[1]], argv[[2]])) [1] 1208822400 1208908800 1208995200 1209081600 1209168000 1209254400 +##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt#Output.MayIgnoreErrorContext# +#.Internal(as.POSIXlt(, 1)) +Error in .Internal(as.POSIXlt(, 1)) : argument 1 is empty + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt#Output.MayIgnoreErrorContext# +#.Internal(as.POSIXlt(2, )) +Error in .Internal(as.POSIXlt(2, )) : argument 2 is empty + ##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt1# #argv <- list(structure(c(2147483648.4, 2147483648.8), class = c('POSIXct', 'POSIXt'), tzone = ''), ''); .Internal(as.POSIXlt(argv[[1]], argv[[2]])) [1] "2038-01-19 03:14:08 GMT" "2038-01-19 03:14:08 GMT" @@ -5370,6 +5810,10 @@ quote(80L) #argv <- list(list(quote(quote), NA));as.call(argv[[1]]); quote(NA) +##com.oracle.truffle.r.test.builtins.TestBuiltin_ascharacter.testAsCharacter# +#{ as.character() } +character(0) + ##com.oracle.truffle.r.test.builtins.TestBuiltin_ascharacter.testAsCharacter# #{ as.character(1) } [1] "1" @@ -5781,6 +6225,10 @@ character(0) Warning message: NAs introduced by coercion +##com.oracle.truffle.r.test.builtins.TestBuiltin_ascomplex.testAsComplex# +#{ as.complex() } +complex(0) + ##com.oracle.truffle.r.test.builtins.TestBuiltin_ascomplex.testAsComplex# #{ as.complex(0) } [1] 0+0i @@ -5913,6 +6361,10 @@ Time differences in hours Warning message: NAs introduced by coercion +##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble# +#{ as.double() } +numeric(0) + ##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble#Output.IgnoreWarningContext# #{ as.double(10+2i) } [1] 10 @@ -5983,7 +6435,7 @@ numeric(0) #argv <- list(structure(c(21, 16.4, 18.7, 16.8, 17.8, 10.9, 14, 3.5, 4.3, 3.5, 2.7, 6, 14, 2.3), .Dim = c(7L, 2L), .Dimnames = list(c('L', 'NL', 'D', 'B', 'F', 'IRL', 'UK'), c('x', 'y'))));as.double(argv[[1]]); [1] 21.0 16.4 18.7 16.8 17.8 10.9 14.0 3.5 4.3 3.5 2.7 6.0 14.0 2.3 -##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testasdouble14#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testasdouble14# #argv <- list(c(0, 0, 0, 0, 0, 1.75368801162502e-134, 0, 0, 0, 2.60477585273833e-251, 1.16485035372295e-260, 0, 1.53160350210786e-322, 0.333331382328728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.44161262707712e-123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.96881154539801e-173, 0, 8.23599653846971e-150, 0, 0, 0, 0, 6.51733217171342e-10, 0, 2.36840184577368e-67, 0, 9.43484083575241e-307, 0, 1.59959906013772e-89, 0, 8.73836857865035e-286, 7.09716190970993e-54, 0, 0, 0, 1.530425353017e-274, 8.57590058044552e-14, 0.333333106397154, 0, 0, 1.36895217898448e-199, 2.0226102635783e-177, 5.50445388209462e-42, 0, 0, 0, 0, 1.07846402051283e-44, 1.88605464411243e-186, 1.09156111051203e-26, 0, 3.07028772732371e-124, 0.333333209689785, 0, 0, 0, 0, 0, 0, 3.09816093866831e-94, 0, 0, 4.75227273320951e-272, 0, 0, 2.30093251441394e-06, 0, 0, 1.27082826644707e-274, 0, 0, 0, 0, 0, 0, 0, 4.5662025456054e-65, 0, 2.77995853978268e-149, 0, 0, 0));as.double(argv[[1]]); [1] 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 [6] 1.753688e-134 0.000000e+00 0.000000e+00 0.000000e+00 2.604776e-251 @@ -6231,7 +6683,7 @@ a + foo(c) * b #foo <- function(x) x*2; f <- function() a+foo(c)*b; as.function(c(alist(a=1+14, b=foo(x),c=), body(f)))(c=3,b=1) [1] 21 -##com.oracle.truffle.r.test.builtins.TestBuiltin_asfunction.testasfunction# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asfunction.testasfunction#Output.IgnoreErrorContext# #{ .Internal(as.function.default(alist(a+b), "foo")) } Error in as.function.default(alist(a + b), "foo") : invalid environment @@ -6378,6 +6830,10 @@ numeric(0) Warning message: NAs introduced by coercion +##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.testAsInteger# +#{ as.integer() } +integer(0) + ##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.testAsInteger# #{ as.integer(-0/0) } [1] NA @@ -6722,6 +7178,18 @@ logical(0) [9,] "a" "a" "a" "a" "a" "a" "a" "a" "a" "a" [10,] "a" "a" "a" "a" "a" "a" "a" "a" "a" "a" +##com.oracle.truffle.r.test.builtins.TestBuiltin_asmatrix.testMatrix# +#{ matrix(1.1:16.1,2,2)} + [,1] [,2] +[1,] 1.1 3.1 +[2,] 2.1 4.1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_asmatrix.testMatrix# +#{ matrix(1:16,2,2)} + [,1] [,2] +[1,] 1 3 +[2,] 2 4 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_asmatrix.testMatrix# #{ matrix(1:4, nrow=2) } [,1] [,2] @@ -6976,6 +7444,10 @@ Warning messages: Warning message: out-of-range values treated as 0 in coercion to raw +##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw# +#{ as.raw() } +Error in as.raw() : 0 arguments passed to 'as.raw' which requires 1 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWarningContext# #{ as.raw(-1) } [1] 00 @@ -7148,7 +7620,7 @@ x ~ z #{ as.vector("foo") } [1] "foo" -##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.ImprovedErrorContext# #{ as.vector("foo", "bar") } Error in as.vector(x, mode) : invalid 'mode' argument @@ -7156,13 +7628,13 @@ Error in as.vector(x, mode) : invalid 'mode' argument #{ as.vector("foo", "character") } [1] "foo" -##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector# #{ as.vector("foo", "double") } [1] NA Warning message: In as.vector("foo", "double") : NAs introduced by coercion -##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector# #{ as.vector("foo", "integer") } [1] NA Warning message: @@ -7178,13 +7650,13 @@ In as.vector("foo", "integer") : NAs introduced by coercion #{ as.vector("foo", "logical") } [1] NA -##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector# #{ as.vector("foo", "numeric") } [1] NA Warning message: In as.vector("foo", "numeric") : NAs introduced by coercion -##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector# #{ as.vector("foo", "raw") } [1] 00 Warning messages: @@ -7192,15 +7664,15 @@ Warning messages: 2: In as.vector("foo", "raw") : out-of-range values treated as 0 in coercion to raw -##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.ImprovedErrorContext# #{ as.vector(42, NULL) } Error in as.vector(x, mode) : invalid 'mode' argument -##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.ImprovedErrorContext# #{ as.vector(42, c("character", "character")) } Error in as.vector(x, mode) : invalid 'mode' argument -##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.ImprovedErrorContext# #{ as.vector(42, character()) } Error in as.vector(x, mode) : invalid 'mode' argument @@ -7212,7 +7684,7 @@ NULL #{ as.vector(NULL, "list") } list() -##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector# #{ as.vector(c("foo", "bar"), "raw") } [1] 00 00 Warning messages: @@ -7959,15 +8431,15 @@ Error in atan2() : argument "y" is missing, with no default #{ atan2(0.7) } Error in atan2(0.7) : argument "x" is missing, with no default -##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testTrigExp# +##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testTrigExp#Output.ImprovedErrorContext# #{ atan2(2, as.symbol('45')) } Error in atan2(y, x) : non-numeric argument to mathematical function -##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testTrigExp# +##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testTrigExp#Output.ImprovedErrorContext# #{ atan2(2, new.env()) } Error in atan2(y, x) : non-numeric argument to mathematical function -##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testTrigExp# +##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testTrigExp#Output.ImprovedErrorContext# #{ atan2(NULL, 1) } Error in atan2(y, x) : non-numeric argument to mathematical function @@ -8057,7 +8529,7 @@ Error: object 'colNameX' not found #attach('string') Error in attach("string") : file 'string' not found -##com.oracle.truffle.r.test.builtins.TestBuiltin_attach.testArguments#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_attach.testArguments# #attach(list(), name=42) Error in attach(list(), name = 42) : invalid 'name' argument @@ -8383,11 +8855,11 @@ NULL #argv <- list(structure(list(Fr = c(32, 53, 10, 3, 11, 50, 10, 30, 10, 25, 7, 5, 3, 15, 7, 8, 36, 66, 16, 4, 9, 34, 7, 64, 5, 29, 7, 5, 2, 14, 7, 8), Hair = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c('Black', 'Brown', 'Red', 'Blond'), class = 'factor'), Eye = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L), .Label = c('Brown', 'Blue', 'Hazel', 'Green'), class = 'factor'), Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c('Male', 'Female'), class = 'factor')), .Names = c('Fr', 'Hair', 'Eye', 'Sex'), terms = quote(Fr ~ (Hair + Eye + Sex)^2), row.names = c(NA, 32L), class = 'data.frame'), 'terms');attr(argv[[1]],argv[[2]]); Fr ~ (Hair + Eye + Sex)^2 -##com.oracle.truffle.r.test.builtins.TestBuiltin_attrassign.testArgsCasts#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_attrassign.testArgsCasts# #x<-42; attr(x, 42) <- NULL Error in attr(x, 42) <- NULL : 'name' must be non-null character string -##com.oracle.truffle.r.test.builtins.TestBuiltin_attrassign.testArgsCasts#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_attrassign.testArgsCasts# #x<-42; attr(x, NULL) <- NULL Error in attr(x, NULL) <- NULL : 'name' must be non-null character string @@ -9502,6 +9974,22 @@ numeric(0) #argv <- structure(list(a = 1e-200, b = 1e-200), .Names = c('a', 'b'));do.call('beta', argv) [1] 2e+200 +##com.oracle.truffle.r.test.builtins.TestBuiltin_bincode.testBincode#Output.MayIgnoreErrorContext# +#{ .Internal(bincode(, 1, T, T)) } +Error in .Internal(bincode(, 1, T, T)) : argument 1 is empty + +##com.oracle.truffle.r.test.builtins.TestBuiltin_bincode.testBincode#Output.MayIgnoreErrorContext# +#{ .Internal(bincode(1, ,T, T)) } +Error in .Internal(bincode(1, , T, T)) : argument 2 is empty + +##com.oracle.truffle.r.test.builtins.TestBuiltin_bincode.testBincode# +#{ .Internal(bincode(2, NULL, T, T)) } +[1] NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_bincode.testBincode# +#{ .Internal(bincode(NULL, 2, T, T)) } +integer(0) + ##com.oracle.truffle.r.test.builtins.TestBuiltin_bincode.testBincode# #{ x <- c(0, 0.01, 0.5, 0.99, 1); b <- c(0, 0, 1, 1); .bincode(x, b, FALSE) } [1] 2 2 2 2 NA @@ -9599,7 +10087,7 @@ Error in bitwAnd(c(1, 2, 3, 4), c(TRUE)) : #argv <- list(structure(integer(0), class = 'hexmode'), structure(integer(0), class = 'hexmode')); .Internal(bitwiseAnd(argv[[1]], argv[[2]])) integer(0) -##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseNot.testBitwiseFunctions#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseNot.testBitwiseFunctions# #{ bitwNot(TRUE) } Error in bitwNot(TRUE) : unimplemented type 'logical' in 'bitNot' @@ -9641,6 +10129,14 @@ Error in bitwOr(c(1, 2, 3, 4), c(3 + (0+3i))) : [25] -33554432 -67108864 -134217728 -268435456 -536870912 -1073741824 [31] NA +##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions#Output.MayIgnoreErrorContext# +#{ .Internal(bitwiseShiftL(, 1))} +Error in .Internal(bitwiseShiftL(, 1)) : argument 1 is empty + +##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions#Output.MayIgnoreErrorContext# +#{ .Internal(bitwiseShiftL(200, ))} +Error in .Internal(bitwiseShiftL(200, )) : argument 2 is empty + ##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions# #{ bitwShiftL(TRUE, c(TRUE, FALSE)) } Error in bitwShiftL(TRUE, c(TRUE, FALSE)) : @@ -9669,7 +10165,7 @@ In bitwShiftL(c(1, 2, 3, 4), c("a")) : NAs introduced by coercion Error in bitwShiftL(c(3 + (0+3i)), c(3, 2, 4)) : unimplemented type 'complex' in 'bitShiftL' -##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions# #{ bitwShiftL(c(3,2,4), c(3+3i)) } [1] 24 16 32 Warning message: @@ -9680,6 +10176,14 @@ In bitwShiftL(c(3, 2, 4), c(3 + (0+3i))) : #{ bitwShiftL(c(8,4,2), NULL) } integer(0) +##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftR.testBitwiseFunctions#Output.MayIgnoreErrorContext# +#{ .Internal(bitwiseShiftR(, 1))} +Error in .Internal(bitwiseShiftR(, 1)) : argument 1 is empty + +##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftR.testBitwiseFunctions#Output.MayIgnoreErrorContext# +#{ .Internal(bitwiseShiftR(200, ))} +Error in .Internal(bitwiseShiftR(200, )) : argument 2 is empty + ##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftR.testBitwiseFunctions#Ignored.Unknown# #{ bitwShiftR(c(1,2,3,4), c("Hello")) } [1] NA NA NA NA @@ -9698,7 +10202,7 @@ In bitwShiftR(c(1, 2, 3, 4), c("Hello")) : NAs introduced by coercion #{ bitwShiftR(c(25,57,66), c(10,20,30,40,50,60)) } [1] 0 0 0 NA NA NA -##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftR.testBitwiseFunctions#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftR.testBitwiseFunctions# #{ bitwShiftR(c(3,2,4), c(3+3i)) } [1] 0 0 0 Warning message: @@ -9748,7 +10252,7 @@ Error in bitwXor(c("r"), c(16, 17)) : 'a' and 'b' must have the same type #argv <- list(function (from, strict = TRUE) from); .Internal(body(argv[[1]])) from -##com.oracle.truffle.r.test.builtins.TestBuiltin_body.testbody4#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_body.testbody4# #argv <- list(.Primitive('/')); .Internal(body(argv[[1]])) NULL @@ -11636,17 +12140,17 @@ hello ##com.oracle.truffle.r.test.builtins.TestBuiltin_cat.testCatUnsupportedArgs# #cat(list(), expression(), sep='this-should-be-ok') this-should-be-ok -##com.oracle.truffle.r.test.builtins.TestBuiltin_cat.testCatUnsupportedArgs# +##com.oracle.truffle.r.test.builtins.TestBuiltin_cat.testCatUnsupportedArgs#Output.ImprovedErrorContext# #cat(list(1,2,3)) Error in cat(list(...), file, sep, fill, labels, append) : argument 1 (type 'list') cannot be handled by 'cat' -##com.oracle.truffle.r.test.builtins.TestBuiltin_cat.testCatUnsupportedArgs# +##com.oracle.truffle.r.test.builtins.TestBuiltin_cat.testCatUnsupportedArgs#Output.ImprovedErrorContext# #cat(parse(text='42')) Error in cat(list(...), file, sep, fill, labels, append) : argument 1 (type 'expression') cannot be handled by 'cat' -##com.oracle.truffle.r.test.builtins.TestBuiltin_cat.testCatUnsupportedArgs# +##com.oracle.truffle.r.test.builtins.TestBuiltin_cat.testCatUnsupportedArgs#Output.ImprovedErrorContext# #cat(quote(3+3)) Error in cat(list(...), file, sep, fill, labels, append) : argument 1 (type 'language') cannot be handled by 'cat' @@ -11956,6 +12460,12 @@ c 2 a c 1 7 42 +##com.oracle.truffle.r.test.builtins.TestBuiltin_cbind.testCbind# +#{x <- numeric(); y <- matrix(2,2); dimnames(y) <- list(c(NA_character_,NA_character_), c(NA_character_)); rbind(x, y) } + <NA> +<NA> 2 +<NA> 2 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_cbind.testDimnames# #{ attributes(cbind(1L)) } $dim @@ -12824,6 +13334,17 @@ structure(integer(0), .Dim = c(0L, 3L), .Dimnames = list(NULL, 5th break 1201 1466 6th break 1467 1600 +##com.oracle.truffle.r.test.builtins.TestBuiltin_cbind.testcbind6# +#cbind2(3, 4) + [,1] [,2] +[1,] 3 4 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_cbind.testcbind6# +#cbind2(matrix(1:10, 2, 2), matrix(11:20, 2, 2)) + [,1] [,2] [,3] [,4] +[1,] 1 3 11 13 +[2,] 2 4 12 14 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_ceiling.testCeiling# #{ ceiling(c(0.2,-3.4,NA,0/0,1/0)) } [1] 1 -3 NA NaN Inf @@ -13253,6 +13774,18 @@ function() 42 #{ x=1;class(x)<-"character"; x} [1] "1" +##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#Output.MayIgnoreErrorContext# +#{`class<-`(, "foo") } +Error in `class<-`(, "foo") : argument 1 is empty + +##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#Output.MayIgnoreErrorContext# +#{`class<-`(, ) } +Error in `class<-`(, ) : argument 1 is empty + +##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#Output.MayIgnoreErrorContext# +#{`class<-`(NULL, "first") } +Error: attempt to set an attribute on NULL + ##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass# #{x<-"abc";class(x)<-"a";class(x)<-"character";x;} [1] "abc" @@ -13374,6 +13907,10 @@ Error in class(x) <- "array" : #{x<-c(2+3i,4+5i);class(x)<-"a";class(x)<-"complex";x;} [1] 2+3i 4+5i +##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#Output.MayIgnoreErrorContext# +#{x=1; `class<-`(x, ) } +Error in `class<-`(x, ) : argument 2 is empty + ##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass# #{x=1; class(x)<-"first"; x;} [1] 1 @@ -14362,7 +14899,7 @@ attr(,"foo") Error in `[[<-.data.frame`(`*tmp*`, i, value = numeric(0)) : replacement has 0 rows, data has 5 -##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr11#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr11# #argv <- list(structure(list(srcfile = c(NA, '/home/lzhao/hg/r-instrumented/library/stats/R/stats', '/home/lzhao/hg/r-instrumented/library/stats/R/stats', '/home/lzhao/hg/r-instrumented/library/stats/R/stats'), frow = c(NA, 2228L, 2369L, 2379L), lrow = c(NA, 2228L, 2369L, 2380L)), .Names = c('srcfile', 'frow', 'lrow'), row.names = c(NA, 4L), class = 'data.frame'), structure(list(srcfile = NULL, frow = NULL, lrow = NULL), .Names = c('srcfile', 'frow', 'lrow'), row.names = c(NA, 4L), class = 'data.frame')); .Internal(copyDFattr(argv[[1]], argv[[2]])) srcfile frow lrow 1 NULL NULL NULL @@ -14373,7 +14910,7 @@ Warning message: In format.data.frame(x, digits = digits, na.encode = FALSE) : corrupt data frame: columns will be truncated or padded with NAs -##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr12#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr12# #argv <- list(structure(list(y = c(73, 73, 70, 74, 75, 115, 105, 107, 124, 107, 116, 125, 102, 144, 178, 149, 177, 124, 157, 128, 169, 165, 186, 152, 181, 139, 173, 151, 138, 181, 152, 188, 173, 196, 180, 171, 188, 174, 198, 172, 176, 162, 188, 182, 182, 141, 191, 190, 159, 170, 163, 197), x = c(1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 11, 12)), .Names = c('y', 'x'), class = 'data.frame', row.names = c(NA, 52L), terms = quote(~y + x)), structure(list(y = NULL, x = NULL), .Names = c('y', 'x'), class = 'data.frame', row.names = c(NA, 52L), terms = quote(~y + x))); .Internal(copyDFattr(argv[[1]], argv[[2]])) y x 1 NULL NULL @@ -14454,7 +14991,7 @@ attr(,"class") attr(,"class")attr(,"package") [1] ".GlobalEnv" -##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr14#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr14# #argv <- list(structure(list(y = c(-0.667819876370237, 0.170711734013213, 0.552921941721332, -0.253162069270378, -0.00786394222146348, 0.0246733498130512, 0.0730305465518564, -1.36919169254062, 0.0881443844426084, -0.0834190388782434)), .Names = 'y', class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ 0)), structure(list(y = NULL), .Names = 'y', class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ 0))); .Internal(copyDFattr(argv[[1]], argv[[2]])) y 1 NULL @@ -14471,7 +15008,7 @@ Warning message: In format.data.frame(x, digits = digits, na.encode = FALSE) : corrupt data frame: columns will be truncated or padded with NAs -##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr15#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr15# #argv <- list(structure(list(`cbind(w = weight, w2 = weight^2)` = structure(c(4.17, 5.58, 5.18, 6.11, 4.5, 4.61, 5.17, 4.53, 5.33, 5.14, 4.81, 4.17, 4.41, 3.59, 5.87, 3.83, 6.03, 4.89, 4.32, 4.69, 17.3889, 31.1364, 26.8324, 37.3321, 20.25, 21.2521, 26.7289, 20.5209, 28.4089, 26.4196, 23.1361, 17.3889, 19.4481, 12.8881, 34.4569, 14.6689, 36.3609, 23.9121, 18.6624, 21.9961), .Dim = c(20L, 2L), .Dimnames = list(NULL, c('w', 'w2'))), group = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c('Ctl', 'Trt'), class = 'factor')), .Names = c('cbind(w = weight, w2 = weight^2)', 'group'), class = 'data.frame', row.names = c(NA, 20L), terms = quote(cbind(w = weight, w2 = weight^2) ~ group)), structure(list(`cbind(w = weight, w2 = weight^2)` = NULL, group = NULL), .Names = c('cbind(w = weight, w2 = weight^2)', 'group'), class = 'data.frame', row.names = c(NA, 20L), terms = quote(cbind(w = weight, w2 = weight^2) ~ group))); .Internal(copyDFattr(argv[[1]], argv[[2]])) cbind(w = weight, w2 = weight^2) group 1 NULL NULL @@ -14498,7 +15035,7 @@ Warning message: In format.data.frame(x, digits = digits, na.encode = FALSE) : corrupt data frame: columns will be truncated or padded with NAs -##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr16#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr16# #argv <- list(structure(list(Y = c(130L, 157L, 174L, 117L, 114L, 161L, 141L, 105L, 140L, 118L, 156L, 61L, 91L, 97L, 100L, 70L, 108L, 126L, 149L, 96L, 124L, 121L, 144L, 68L, 64L, 112L, 86L, 60L, 102L, 89L, 96L, 89L, 129L, 132L, 124L, 74L, 89L, 81L, 122L, 64L, 103L, 132L, 133L, 70L, 89L, 104L, 117L, 62L, 90L, 100L, 116L, 80L, 82L, 94L, 126L, 63L, 70L, 109L, 99L, 53L, 74L, 118L, 113L, 89L, 82L, 86L, 104L, 97L, 99L, 119L, 121L), B = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L), .Label = c('I', 'II', 'III', 'IV', 'V', 'VI'), class = 'factor'), V = structure(c(3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), .Label = c('Golden.rain', 'Marvellous', 'Victory'), class = 'factor'), N = structure(c(2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c('0.0cwt', '0.2cwt', '0.4cwt', '0.6cwt'), class = 'factor')), .Names = c('Y', 'B', 'V', 'N'), terms = quote(Y ~ B + V + N + V:N), row.names = 2:72, class = 'data.frame'), structure(list(Y = NULL, B = NULL, V = NULL, N = NULL), .Names = c('Y', 'B', 'V', 'N'), terms = quote(Y ~ B + V + N + V:N), row.names = 2:72, class = 'data.frame')); .Internal(copyDFattr(argv[[1]], argv[[2]])) Y B V N 2 NULL NULL NULL NULL @@ -14576,7 +15113,7 @@ Warning message: In format.data.frame(x, digits = digits, na.encode = FALSE) : corrupt data frame: columns will be truncated or padded with NAs -##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr17#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr17# #argv <- list(structure(list(Fr = c(32, 53, 10, 3, 11, 50, 10, 30, 10, 25, 7, 5, 3, 15, 7, 8, 36, 66, 16, 4, 9, 34, 7, 64, 5, 29, 7, 5, 2, 14, 7, 8), Hair = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c('Black', 'Brown', 'Red', 'Blond'), class = 'factor'), Eye = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L), .Label = c('Brown', 'Blue', 'Hazel', 'Green'), class = 'factor'), Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c('Male', 'Female'), class = 'factor')), .Names = c('Fr', 'Hair', 'Eye', 'Sex'), class = 'data.frame', row.names = c(NA, 32L), terms = quote(Fr ~ (Hair + Eye + Sex)^2)), structure(list(Fr = NULL, Hair = NULL, Eye = NULL, Sex = NULL), .Names = c('Fr', 'Hair', 'Eye', 'Sex'), class = 'data.frame', row.names = c(NA, 32L), terms = quote(Fr ~ (Hair + Eye + Sex)^2))); .Internal(copyDFattr(argv[[1]], argv[[2]])) Fr Hair Eye Sex 1 NULL NULL NULL NULL @@ -14615,7 +15152,7 @@ Warning message: In format.data.frame(x, digits = digits, na.encode = FALSE) : corrupt data frame: columns will be truncated or padded with NAs -##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr18#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr18# #argv <- list(structure(list(Employed = c(60.323, 61.122, 60.171, 61.187, 63.221, 63.639, 64.989, 63.761, 66.019, 67.857, 68.169, 66.513, 68.655, 69.564, 69.331, 70.551), GNP.deflator = c(83, 88.5, 88.2, 89.5, 96.2, 98.1, 99, 100, 101.2, 104.6, 108.4, 110.8, 112.6, 114.2, 115.7, 116.9), GNP = c(234.289, 259.426, 258.054, 284.599, 328.975, 346.999, 365.385, 363.112, 397.469, 419.18, 442.769, 444.546, 482.704, 502.601, 518.173, 554.894), Unemployed = c(235.6, 232.5, 368.2, 335.1, 209.9, 193.2, 187, 357.8, 290.4, 282.2, 293.6, 468.1, 381.3, 393.1, 480.6, 400.7), Armed.Forces = c(159, 145.6, 161.6, 165, 309.9, 359.4, 354.7, 335, 304.8, 285.7, 279.8, 263.7, 255.2, 251.4, 257.2, 282.7), Population = c(107.608, 108.632, 109.773, 110.929, 112.075, 113.27, 115.094, 116.219, 117.388, 118.734, 120.445, 121.95, 123.366, 125.368, 127.852, 130.081), Year = 1947:1962), .Names = c('Employed', 'GNP.deflator', 'GNP', 'Unemployed', 'Armed.Forces', 'Population', 'Year'), class = 'data.frame', row.names = 1947:1962, terms = quote(Employed ~ GNP.deflator + GNP + Unemployed + Armed.Forces + Population + Year)), structure(list(Employed = NULL, GNP.deflator = NULL, GNP = NULL, Unemployed = NULL, Armed.Forces = NULL, Population = NULL, Year = NULL), .Names = c('Employed', 'GNP.deflator', 'GNP', 'Unemployed', 'Armed.Forces', 'Population', 'Year'), class = 'data.frame', row.names = 1947:1962, terms = quote(Employed ~ GNP.deflator + GNP + Unemployed + Armed.Forces + Population + Year))); .Internal(copyDFattr(argv[[1]], argv[[2]])) Employed GNP.deflator GNP Unemployed Armed.Forces Population Year 1947 NULL NULL NULL NULL NULL NULL NULL @@ -14643,7 +15180,7 @@ In format.data.frame(x, digits = digits, na.encode = FALSE) : Error in `[[<-.data.frame`(`*tmp*`, i, value = numeric(0)) : replacement has 0 rows, data has 4 -##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr2#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr2# #argv <- list(structure(list(y = c(2.30923841792462, 3.23011719303818, 2.9161246695212, 3.35931329373059, 5.3777049208621, 5.63518136825043, 7.37725908636056, 7.75621985157329, 10.1175871700049, 8.86877085545769), x1 = 1:10, x2 = 1:10, x3 = c(0.1, 0.4, 0.9, 1.6, 2.5, 3.6, 4.9, 6.4, 8.1, 10)), .Names = c('y', 'x1', 'x2', 'x3'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x1 + x2 + x3)), structure(list(y = NULL, x1 = NULL, x2 = NULL, x3 = NULL), .Names = c('y', 'x1', 'x2', 'x3'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x1 + x2 + x3))); .Internal(copyDFattr(argv[[1]], argv[[2]])) y x1 x2 x3 1 NULL NULL NULL NULL @@ -14660,7 +15197,7 @@ Warning message: In format.data.frame(x, digits = digits, na.encode = FALSE) : corrupt data frame: columns will be truncated or padded with NAs -##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr20#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr20# #argv <- list(structure(list(`cbind(X, M)` = structure(c(68, 42, 37, 24, 66, 33, 47, 23, 63, 29, 57, 19, 42, 30, 52, 43, 50, 23, 55, 47, 53, 27, 49, 29), .Dim = c(12L, 2L), .Dimnames = list(NULL, c('X', 'M'))), M.user = structure(c(1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L), .Label = c('N', 'Y'), class = 'factor'), Temp = structure(c(2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L), .Label = c('High', 'Low'), class = 'factor'), Soft = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L), .Label = c('Hard', 'Medium', 'Soft'), class = 'factor')), .Names = c('cbind(X, M)', 'M.user', 'Temp', 'Soft'), class = 'data.frame', row.names = c('1', '3', '5', '7', '9', '11', '13', '15', '17', '19', '21', '23'), terms = quote(cbind(X, M) ~ M.user + Temp + Soft)), structure(list(`cbind(X, M)` = NULL, M.user = NULL, Temp = NULL, Soft = NULL), .Names = c('cbind(X, M)', 'M.user', 'Temp', 'Soft'), class = 'data.frame', row.names = c('1', '3', '5', '7', '9', '11', '13', '15', '17', '19', '21', '23'), terms = quote(cbind(X, M) ~ M.user + Temp + Soft))); .Internal(copyDFattr(argv[[1]], argv[[2]])) cbind(X, M) M.user Temp Soft 1 NULL NULL NULL NULL @@ -14679,7 +15216,7 @@ Warning message: In format.data.frame(x, digits = digits, na.encode = FALSE) : corrupt data frame: columns will be truncated or padded with NAs -##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr3#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr3# #argv <- list(structure(list(y = c(-0.0561287395290008, -0.155795506705329, -1.47075238389927, -0.47815005510862, 0.417941560199702, 1.35867955152904, -0.102787727342996, 0.387671611559369, -0.0538050405829051, -1.37705955682861), x = c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE), z = 1:10), .Names = c('y', 'x', 'z'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x * z)), structure(list(y = NULL, x = NULL, z = NULL), .Names = c('y', 'x', 'z'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x * z))); .Internal(copyDFattr(argv[[1]], argv[[2]])) y x z 1 NULL NULL NULL @@ -14701,7 +15238,7 @@ In format.data.frame(x, digits = digits, na.encode = FALSE) : [1] surname nationality deceased <0 rows> (or 0-length row.names) -##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr5#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr5# #argv <- list(structure(list(A = 0:10, B = 10:20, `NA` = 20:30), .Names = c('A', 'B', NA), row.names = c(NA, -11L), class = 'data.frame'), structure(list(A = NULL, B = NULL, `NA` = NULL), .Names = c('A', 'B', NA), row.names = c(NA, -11L), class = 'data.frame')); .Internal(copyDFattr(argv[[1]], argv[[2]])) A B NA 1 NULL NULL NULL @@ -14719,7 +15256,7 @@ Warning message: In format.data.frame(x, digits = digits, na.encode = FALSE) : corrupt data frame: columns will be truncated or padded with NAs -##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr6#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr6# #argv <- list(structure(list(`Surv(stop, status * as.numeric(event), type = 'mstate')` = structure(c(760, 2160, 5441, 277, 1815, 2587, 547, 1125, 2010, 2422, 6155, 1767, 61, 60, 7807, 7732, 6126, 7921, 3590, 5231, 5384, 5934, 6415, 6789, 6778, 3561, 4505, 3987, 4726, 5550, 5216, 5757, 2345, 6931, 6760, 5796, 4810, 5143, 3091, 3316, 700, 1706, 5088, 944, 2466, 1706, 7364, 1857, 9510, 9603, 31, 7479, 2006, 2588, 2983, 8761, 3932, 4201, 5293, 273, 2223, 4249, 5308, 8327, 499, 5789, 7417, 3242, 3275, 10359, 10852, 362, 9993, 1795, 3562, 4139, 4840, 4959, 547, 4119, 8308, 1674, 2953, 3776, 1369, 7911, 7519, 9318, 4370, 7301, 1642, 4169, 7417, 6117, 4536, 7235, 6723, 7397, 7428, 2084, 4066, 1673, 2860, 0, 3773, 4810, 4206, 2314, 4065, 8961, 6143, 517, 3837, 7498, 2815, 8806, 7668, 12457, 8600, 7003, 2435, 1826, 2403, 3805, 4901, 365, 6642, 3318, 3012, 1431, 2223, 4962, 5982, 638, 3346, 4996, 6800, 7454, 8887, 5024, 2833, 4232, 5238, 3186, 3380, 3382, 8100, 1766, 7184, 8059, 6008, 5047, 2236, 8165, 4224, 2844, 6256, 7370, 3560, 4939, 4941, 2230, 3068, 152, 10122, 3226, 3943, 518, 8569, 845, 2099, 8006, 8052, 9560, 0, 7965, 7470, 8133, 809, 153, 1851, 3010, 2121, 7085, 5068, 7093, 5930, 6878, 8080, 791, 6626, 3962, 1116, 1249, 9257, 1077, 566, 174, 4627, 5022, 2070, 3012, 1625, 6607, 8381, 8389, 1005, 3895, 4236, 6970, 8497, 2861, 8487, 3227, 8030, 8023, 31, 2435, 518, 4758, 7958, 7884, 4453, 6349, 7862, 1392, 3167, 6025, 4656, 1767, 7736, 2678, 2191, 3658, 7758, 8009, 2556, 3511, 7954, 822, 4321, 5151, 7545, 7576, 32, 7875, 5236, 7106, 2802, 7898, 3014, 7867, 5354, 2989, 7555, 6089, 8697, 6479, 1826, 5917, 792, 1431, 1434, 4763, 2910, 6209, 5824, 2400, 1400, 3027, 7198, 7247, 2557, 3855, 61, 7410, 1492, 7160, 7899, 5181, 7280, 3448, 7381, 2434, 6763, 7065, 1218, 1554, 7533, 7288, 2922, 5988, 2495, 5234, 9598, 2953, 2961, 4539, 3775, 6524, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 0, 2, 1, 2, 2, 0, 2, 1, 2, 0, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 2, 1, 2, 2, 0, 1, 2, 1, 2, 2, 2, 2, 0, 2, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 2, 1, 2, 2, 1, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 2, 0, 2, 2, 1, 0, 2, 2, 0, 0, 2, 0, 2, 1, 2, 1, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 0, 0, 2, 2, 1, 2, 2, 1, 2, 0, 2, 1, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 1, 2, 1, 2, 2, 0, 2, 2, 2, 0, 2, 2, 1, 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 1, 2, 0, 2, 2, 2, 1, 2, 1, 2, 2, 2, 0, 0, 2, 1, 2, 1, 0, 1, 0, 2, 0, 0, 2, 2, 2, 2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 1, 2, 0, 0, 1, 2, 0, 2, 1, 2, 1, 2, 2, 0, 1, 2, 1, 0, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 0, 0, 1, 2, 2, 0, 2, 0, 2, 2, 0, 2, 0, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 2, 0, 1, 2, 2, 1, 2), .Dim = c(300L, 2L), .Dimnames = list(NULL, c('time', 'status')), type = 'mright', states = c('1', '2'), class = 'Surv')), .Names = 'Surv(stop, status * as.numeric(event), type = \'mstate\')', class = 'data.frame', row.names = c(NA, 300L)), structure(list(`Surv(stop, status * as.numeric(event), type = 'mstate')` = NULL), .Names = 'Surv(stop, status * as.numeric(event), type = \'mstate\')', class = 'data.frame', row.names = c(NA, 300L))); .Internal(copyDFattr(argv[[1]], argv[[2]])) Surv(stop, status * as.numeric(event), type = 'mstate') 1 NULL @@ -15513,6 +16050,11 @@ Error: could not find function "crc64" #crc64() Error: could not find function "crc64" +##com.oracle.truffle.r.test.builtins.TestBuiltin_crossprod.testCrossprod#Output.ImprovedErrorContext# +#{ crossprod('asdf', matrix(1:6, ncol=2)) } +Error in crossprod(x, y) : + requires numeric/complex matrix/vector arguments + ##com.oracle.truffle.r.test.builtins.TestBuiltin_crossprod.testCrossprod# #{ crossprod(1:3, matrix(1:6, ncol=2)) } [,1] [,2] @@ -16382,7 +16924,7 @@ Error in print(x, y) : #deparse(1) [1] "1" -##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse#Ignored.OutputFormatting# +##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse# #deparse(1.53160350210786e-322) [1] "1.53160350210786e-322" @@ -16490,6 +17032,10 @@ Error in print(x, y) : #deparse(c(T, F)) [1] "c(TRUE, FALSE)" +##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse# +#deparse(list(`x y`=1)) +[1] "structure(list(\"x y\" = 1), .Names = \"x y\")" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse# #deparse(quote(1/0)) [1] "1/0" @@ -16706,6 +17252,10 @@ Error in print(x, y) : #deparse(quote(cat(c(T, F)))) [1] "cat(c(T, F))" +##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse# +#e <- quote(a <- 1); e[[3]] <- as.raw(c(1,6,9,254)); e +a <- as.raw(c(0x01, 0x06, 0x09, 0xfe)) + ##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse# #unserialize(serialize(quote(!(a <- TRUE)), NULL)) !(a <- TRUE) @@ -16830,13 +17380,9 @@ a[a <- TRUE] #argv <- list(Inf, 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) [1] "Inf" -##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse19#Ignored.Unknown# -#argv <- list(structure(list(Sex = structure(c(2L, 2L, 1L, 1L, 2L, 2L), .Label = c('Female', 'Male'), class = 'factor'), age = c(15, 20, 10, 12, 2, 4), Subject = structure(c(2L, 2L, 1L, 1L, 3L, 3L), .Label = c('F30', 'M01', 'M04'), class = 'factor')), .Names = c('Sex', 'age', 'Subject'), row.names = c(NA, -6L), class = 'data.frame'), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) -[1] "structure(list(Sex = structure(c(2L, 2L, 1L, 1L, 2L, 2L), .Label = c(\"Female\", " -[2] "\"Male\"), class = \"factor\"), age = c(15, 20, 10, 12, 2, 4), Subject = structure(c(2L, " -[3] "2L, 1L, 1L, 3L, 3L), .Label = c(\"F30\", \"M01\", \"M04\"), class = \"factor\")), .Names = c(\"Sex\", " -[4] "\"age\", \"Subject\"), row.names = c(NA, -6L), class = \"data.frame\")" - +##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse19#Output.IgnoreWhitespace# +#cat({argv <- list(structure(list(Sex = structure(c(2L, 2L, 1L, 1L, 2L, 2L), .Label = c('Female', 'Male'), class = 'factor'), age = c(15, 20, 10, 12, 2, 4), Subject = structure(c(2L, 2L, 1L, 1L, 3L, 3L), .Label = c('F30', 'M01', 'M04'), class = 'factor')), .Names = c('Sex', 'age', 'Subject'), row.names = c(NA, -6L), class = 'data.frame'), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))}) +structure(list(Sex = structure(c(2L, 2L, 1L, 1L, 2L, 2L), .Label = c("Female", "Male"), class = "factor"), age = c(15, 20, 10, 12, 2, 4), Subject = structure(c(2L, 2L, 1L, 1L, 3L, 3L), .Label = c("F30", "M01", "M04"), class = "factor")), .Names = c("Sex", "age", "Subject"), row.names = c(NA, -6L), class = "data.frame") ##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse2# #argv <- list(quote(rnorm(1, sd = Inf)), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) [1] "rnorm(1, sd = Inf)" @@ -16857,34 +17403,16 @@ a[a <- TRUE] #argv <- list(quote(cor(Z[, FALSE], use = 'pairwise.complete.obs', method = 'kendall')), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) [1] "cor(Z[, FALSE], use = \"pairwise.complete.obs\", method = \"kendall\")" -##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse24#Ignored.Unknown# -#argv <- list(c(7.4, 8, 12.6, 11.5, 14.3, 14.9, 8.6, 13.8, 20.1, 8.6, 6.9, 9.7, 9.2, 10.9, 13.2, 11.5, 12, 18.4, 11.5, 9.7, 9.7, 16.6, 9.7, 12, 16.6, 14.9, 8, 12, 14.9, 5.7, 7.4, 8.6, 9.7, 16.1, 9.2, 8.6, 14.3, 9.7, 6.9, 13.8, 11.5, 10.9, 9.2, 8, 13.8, 11.5, 14.9, 20.7, 9.2, 11.5, 10.3, 6.3, 1.7, 4.6, 6.3, 8, 8, 10.3, 11.5, 14.9, 8, 6.9, 13.8, 7.4, 6.9, 7.4, 4.6, 4, 10.3, 8, 8.6, 11.5, 11.5, 11.5, 9.7, 11.5, 10.3, 6.3, 7.4, 10.9, 10.3, 15.5, 14.3, 12.6, 9.7, 3.4, 8, 5.7, 9.7, 2.3, 6.3, 6.3, 6.9, 5.1, 2.8, 4.6, 7.4, 15.5, 10.9, 10.3, 10.9, 9.7, 14.9, 15.5, 6.3, 10.9, 11.5, 6.9, 13.8, 10.3, 10.3, 8, 12.6, 9.2, 10.3, 10.3, 16.6, 6.9, 13.2, 14.3, 8, 11.5), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) - [1] "c(7.4, 8, 12.6, 11.5, 14.3, 14.9, 8.6, 13.8, 20.1, 8.6, 6.9, " - [2] "9.7, 9.2, 10.9, 13.2, 11.5, 12, 18.4, 11.5, 9.7, 9.7, 16.6, 9.7, " - [3] "12, 16.6, 14.9, 8, 12, 14.9, 5.7, 7.4, 8.6, 9.7, 16.1, 9.2, 8.6, " - [4] "14.3, 9.7, 6.9, 13.8, 11.5, 10.9, 9.2, 8, 13.8, 11.5, 14.9, 20.7, " - [5] "9.2, 11.5, 10.3, 6.3, 1.7, 4.6, 6.3, 8, 8, 10.3, 11.5, 14.9, " - [6] "8, 6.9, 13.8, 7.4, 6.9, 7.4, 4.6, 4, 10.3, 8, 8.6, 11.5, 11.5, " - [7] "11.5, 9.7, 11.5, 10.3, 6.3, 7.4, 10.9, 10.3, 15.5, 14.3, 12.6, " - [8] "9.7, 3.4, 8, 5.7, 9.7, 2.3, 6.3, 6.3, 6.9, 5.1, 2.8, 4.6, 7.4, " - [9] "15.5, 10.9, 10.3, 10.9, 9.7, 14.9, 15.5, 6.3, 10.9, 11.5, 6.9, " -[10] "13.8, 10.3, 10.3, 8, 12.6, 9.2, 10.3, 10.3, 16.6, 6.9, 13.2, " -[11] "14.3, 8, 11.5)" - +##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse24#Output.IgnoreWhitespace# +#cat({argv <- list(c(7.4, 8, 12.6, 11.5, 14.3, 14.9, 8.6, 13.8, 20.1, 8.6, 6.9, 9.7, 9.2, 10.9, 13.2, 11.5, 12, 18.4, 11.5, 9.7, 9.7, 16.6, 9.7, 12, 16.6, 14.9, 8, 12, 14.9, 5.7, 7.4, 8.6, 9.7, 16.1, 9.2, 8.6, 14.3, 9.7, 6.9, 13.8, 11.5, 10.9, 9.2, 8, 13.8, 11.5, 14.9, 20.7, 9.2, 11.5, 10.3, 6.3, 1.7, 4.6, 6.3, 8, 8, 10.3, 11.5, 14.9, 8, 6.9, 13.8, 7.4, 6.9, 7.4, 4.6, 4, 10.3, 8, 8.6, 11.5, 11.5, 11.5, 9.7, 11.5, 10.3, 6.3, 7.4, 10.9, 10.3, 15.5, 14.3, 12.6, 9.7, 3.4, 8, 5.7, 9.7, 2.3, 6.3, 6.3, 6.9, 5.1, 2.8, 4.6, 7.4, 15.5, 10.9, 10.3, 10.9, 9.7, 14.9, 15.5, 6.3, 10.9, 11.5, 6.9, 13.8, 10.3, 10.3, 8, 12.6, 9.2, 10.3, 10.3, 16.6, 6.9, 13.2, 14.3, 8, 11.5), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))}) +c(7.4, 8, 12.6, 11.5, 14.3, 14.9, 8.6, 13.8, 20.1, 8.6, 6.9, 9.7, 9.2, 10.9, 13.2, 11.5, 12, 18.4, 11.5, 9.7, 9.7, 16.6, 9.7, 12, 16.6, 14.9, 8, 12, 14.9, 5.7, 7.4, 8.6, 9.7, 16.1, 9.2, 8.6, 14.3, 9.7, 6.9, 13.8, 11.5, 10.9, 9.2, 8, 13.8, 11.5, 14.9, 20.7, 9.2, 11.5, 10.3, 6.3, 1.7, 4.6, 6.3, 8, 8, 10.3, 11.5, 14.9, 8, 6.9, 13.8, 7.4, 6.9, 7.4, 4.6, 4, 10.3, 8, 8.6, 11.5, 11.5, 11.5, 9.7, 11.5, 10.3, 6.3, 7.4, 10.9, 10.3, 15.5, 14.3, 12.6, 9.7, 3.4, 8, 5.7, 9.7, 2.3, 6.3, 6.3, 6.9, 5.1, 2.8, 4.6, 7.4, 15.5, 10.9, 10.3, 10.9, 9.7, 14.9, 15.5, 6.3, 10.9, 11.5, 6.9, 13.8, 10.3, 10.3, 8, 12.6, 9.2, 10.3, 10.3, 16.6, 6.9, 13.2, 14.3, 8, 11.5) ##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse25# #argv <- list(1e+05, 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) [1] "1e+05" -##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse26#Ignored.Unknown# -#argv <- list(structure(list(distance = c(26, 25, 29, 31, 21.5, 22.5), age = c(8, 10, 12, 14, 8, 10), Subject = structure(c(2L, 2L, 2L, 2L, 1L, 1L), .Label = c('M02', 'M01'), class = c('ordered', 'factor')), Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L), .Label = c('Male', 'Female'), class = 'factor')), .Names = c('distance', 'age', 'Subject', 'Sex'), row.names = c('1', '2', '3', '4', '5', '6'), class = 'data.frame'), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) -[1] "structure(list(distance = c(26, 25, 29, 31, 21.5, 22.5), age = c(8, " -[2] "10, 12, 14, 8, 10), Subject = structure(c(2L, 2L, 2L, 2L, 1L, " -[3] "1L), .Label = c(\"M02\", \"M01\"), class = c(\"ordered\", \"factor\")), " -[4] " Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L), .Label = c(\"Male\", " -[5] " \"Female\"), class = \"factor\")), .Names = c(\"distance\", \"age\", " -[6] "\"Subject\", \"Sex\"), row.names = c(\"1\", \"2\", \"3\", \"4\", \"5\", \"6\"" -[7] "), class = \"data.frame\")" - +##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse26#Output.IgnoreWhitespace# +#cat({argv <- list(structure(list(distance = c(26, 25, 29, 31, 21.5, 22.5), age = c(8, 10, 12, 14, 8, 10), Subject = structure(c(2L, 2L, 2L, 2L, 1L, 1L), .Label = c('M02', 'M01'), class = c('ordered', 'factor')), Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L), .Label = c('Male', 'Female'), class = 'factor')), .Names = c('distance', 'age', 'Subject', 'Sex'), row.names = c('1', '2', '3', '4', '5', '6'), class = 'data.frame'), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))}) +structure(list(distance = c(26, 25, 29, 31, 21.5, 22.5), age = c(8, 10, 12, 14, 8, 10), Subject = structure(c(2L, 2L, 2L, 2L, 1L, 1L), .Label = c("M02", "M01"), class = c("ordered", "factor")), Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L), .Label = c("Male", "Female"), class = "factor")), .Names = c("distance", "age", "Subject", "Sex"), row.names = c("1", "2", "3", "4", "5", "6" ), class = "data.frame") ##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse27# #argv <- list('\t *ERROR* !!\n', 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) [1] "\"\\t *ERROR* !!\\n\"" @@ -16905,26 +17433,12 @@ a[a <- TRUE] #argv <- list(structure(FALSE, .Dim = 1L), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) [1] "structure(FALSE, .Dim = 1L)" -##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse31#Ignored.Unknown# -#argv <- list(c(0, 0.587785252292473, 0.951056516295154, 0.951056516295154, 0.587785252292473, 1.22464679914735e-16, -0.587785252292473, -0.951056516295154, -0.951056516295154, -0.587785252292473, -2.44929359829471e-16, 0.587785252292473, 0.951056516295154), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) -[1] "c(0, 0.587785252292473, 0.951056516295154, 0.951056516295154, " -[2] "0.587785252292473, 1.22464679914735e-16, -0.587785252292473, " -[3] "-0.951056516295154, -0.951056516295154, -0.587785252292473, -2.44929359829471e-16, " -[4] "0.587785252292473, 0.951056516295154)" - -##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse32#Ignored.Unknown# -#argv <- list(structure(c(39.384847580955, 40.3469409309138, 42.6018205723052, 46.6665176252597, 51.3438205965467, 60.0069972599329, 64.6480892875058, 62.5709232928432, 57.679739382496, 49.5060394945433, 43.474726406114, 39.8236314289602, 38.361391396627, 37.9275637097922, 43.6868952734483, 45.1919846859641, 51.722520194987, 59.3399821539983, 61.9345241730145, 62.1515308754468, 57.6561604617486, 49.2849925780811, 42.606775772378, 39.6394677676018, 38.6328048791077, 38.4418602988203, 43.1520834957543, 45.6551746936999, 51.7999631155049, 59.5021948495759, 62.9217123388139, 62.0751910659837, 57.8048619656866, 49.5091658164884, 42.8045075272742, 40.2515159054665), .Tsp = c(1937, 1939.91666666667, 12), class = 'ts'), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) - [1] "structure(c(39.384847580955, 40.3469409309138, 42.6018205723052, " - [2] "46.6665176252597, 51.3438205965467, 60.0069972599329, 64.6480892875058, " - [3] "62.5709232928432, 57.679739382496, 49.5060394945433, 43.474726406114, " - [4] "39.8236314289602, 38.361391396627, 37.9275637097922, 43.6868952734483, " - [5] "45.1919846859641, 51.722520194987, 59.3399821539983, 61.9345241730145, " - [6] "62.1515308754468, 57.6561604617486, 49.2849925780811, 42.606775772378, " - [7] "39.6394677676018, 38.6328048791077, 38.4418602988203, 43.1520834957543, " - [8] "45.6551746936999, 51.7999631155049, 59.5021948495759, 62.9217123388139, " - [9] "62.0751910659837, 57.8048619656866, 49.5091658164884, 42.8045075272742, " -[10] "40.2515159054665), .Tsp = c(1937, 1939.91666666667, 12), class = \"ts\")" - +##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse31#Output.IgnoreWhitespace# +#cat({argv <- list(c(0, 0.587785252292473, 0.951056516295154, 0.951056516295154, 0.587785252292473, 1.22464679914735e-16, -0.587785252292473, -0.951056516295154, -0.951056516295154, -0.587785252292473, -2.44929359829471e-16, 0.587785252292473, 0.951056516295154), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))}) +c(0, 0.587785252292473, 0.951056516295154, 0.951056516295154, 0.587785252292473, 1.22464679914735e-16, -0.587785252292473, -0.951056516295154, -0.951056516295154, -0.587785252292473, -2.44929359829471e-16, 0.587785252292473, 0.951056516295154) +##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse32#Output.IgnoreWhitespace# +#cat({argv <- list(structure(c(39.384847580955, 40.3469409309138, 42.6018205723052, 46.6665176252597, 51.3438205965467, 60.0069972599329, 64.6480892875058, 62.5709232928432, 57.679739382496, 49.5060394945433, 43.474726406114, 39.8236314289602, 38.361391396627, 37.9275637097922, 43.6868952734483, 45.1919846859641, 51.722520194987, 59.3399821539983, 61.9345241730145, 62.1515308754468, 57.6561604617486, 49.2849925780811, 42.606775772378, 39.6394677676018, 38.6328048791077, 38.4418602988203, 43.1520834957543, 45.6551746936999, 51.7999631155049, 59.5021948495759, 62.9217123388139, 62.0751910659837, 57.8048619656866, 49.5091658164884, 42.8045075272742, 40.2515159054665), .Tsp = c(1937, 1939.91666666667, 12), class = 'ts'), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))}) +structure(c(39.384847580955, 40.3469409309138, 42.6018205723052, 46.6665176252597, 51.3438205965467, 60.0069972599329, 64.6480892875058, 62.5709232928432, 57.679739382496, 49.5060394945433, 43.474726406114, 39.8236314289602, 38.361391396627, 37.9275637097922, 43.6868952734483, 45.1919846859641, 51.722520194987, 59.3399821539983, 61.9345241730145, 62.1515308754468, 57.6561604617486, 49.2849925780811, 42.606775772378, 39.6394677676018, 38.6328048791077, 38.4418602988203, 43.1520834957543, 45.6551746936999, 51.7999631155049, 59.5021948495759, 62.9217123388139, 62.0751910659837, 57.8048619656866, 49.5091658164884, 42.8045075272742, 40.2515159054665), .Tsp = c(1937, 1939.91666666667, 12), class = "ts") ##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse33# #argv <- list(NA_real_, 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) [1] "NA_real_" @@ -16933,57 +17447,9 @@ a[a <- TRUE] #argv <- list(quote(lm(formula = y ~ x1 + x2 + x3)), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) [1] "lm(formula = y ~ x1 + x2 + x3)" -##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse35#Ignored.Unknown# -#argv <- list(structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, 140, 145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166, 171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194, 196, 196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201, 204, 188, 235, 227, 234, 264, 302, 293, 259, 229, 203, 229, 242, 233, 267, 269, 270, 315, 364, 347, 312, 274, 237, 278, 284, 277, 317, 313, 318, 374, 413, 405, 355, 306, 271, 306, 315, 301, 356, 348, 355, 422, 465, 467, 404, 347, 305, 336, 340, 318, 362, 348, 363, 435, 491, 505, 404, 359, 310, 337, 360, 342, 406, 396, 420, 472, 548, 559, 463, 407, 362, 405, 417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390, 432, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 419.147602949539, 391.474665943444, 435.919286153217, 443.935203034261, 455.023399013445, 517.28707821144, 589.71337277669, 582.999919227301, 484.573388713116, 428.878182738437, 368.526582998452, 406.728709993152, 415.660571294428, 388.716535970235, 433.006017658935, 440.885684396326, 451.651900136866, 513.051252429496, 584.327164324967, 577.055407135124, 479.076505013118, 423.494870357491, 363.43932958967, 400.592058645117, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 484.030717075782, 462.954959541421, 526.353307750503, 546.165638262644, 569.502470928676, 657.838443307596, 761.241730163307, 763.280655335144, 642.989004951864, 576.423799567567, 501.429012064338, 559.981301364233, 591.700754553767, 565.210772316967, 642.377841008703, 666.682421047093, 695.547100430962, 804.065022775202, 931.340589597203, 934.837830059897, 788.422986194072, 707.666678543854, 616.37838266375, 689.250456425465), .Dim = c(168L, 3L), .Dimnames = list(NULL, c('structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, ', 'structure(c(419.147602949539, 391.474665943444, 435.919286153217, ', 'structure(c(484.030717075782, 462.954959541421, 526.353307750503, ')), .Tsp = c(1949, 1962.91666666667, 12), class = c('mts', 'ts', 'matrix')), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) - [1] "structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, " - [2] "104, 118, 115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, " - [3] "140, 145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166, " - [4] "171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194, 196, " - [5] "196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201, 204, 188, " - [6] "235, 227, 234, 264, 302, 293, 259, 229, 203, 229, 242, 233, 267, " - [7] "269, 270, 315, 364, 347, 312, 274, 237, 278, 284, 277, 317, 313, " - [8] "318, 374, 413, 405, 355, 306, 271, 306, 315, 301, 356, 348, 355, " - [9] "422, 465, 467, 404, 347, 305, 336, 340, 318, 362, 348, 363, 435, " -[10] "491, 505, 404, 359, 310, 337, 360, 342, 406, 396, 420, 472, 548, " -[11] "559, 463, 407, 362, 405, 417, 391, 419, 461, 472, 535, 622, 606, " -[12] "508, 461, 390, 432, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, " -[13] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, " -[14] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, " -[15] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, " -[16] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, " -[17] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, " -[18] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, " -[19] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, " -[20] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, " -[21] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, " -[22] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 419.147602949539, " -[23] "391.474665943444, 435.919286153217, 443.935203034261, 455.023399013445, " -[24] "517.28707821144, 589.71337277669, 582.999919227301, 484.573388713116, " -[25] "428.878182738437, 368.526582998452, 406.728709993152, 415.660571294428, " -[26] "388.716535970235, 433.006017658935, 440.885684396326, 451.651900136866, " -[27] "513.051252429496, 584.327164324967, 577.055407135124, 479.076505013118, " -[28] "423.494870357491, 363.43932958967, 400.592058645117, NA, NA, " -[29] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, " -[30] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, " -[31] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, " -[32] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, " -[33] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, " -[34] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, " -[35] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, " -[36] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, " -[37] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 484.030717075782, " -[38] "462.954959541421, 526.353307750503, 546.165638262644, 569.502470928676, " -[39] "657.838443307596, 761.241730163307, 763.280655335144, 642.989004951864, " -[40] "576.423799567567, 501.429012064338, 559.981301364233, 591.700754553767, " -[41] "565.210772316967, 642.377841008703, 666.682421047093, 695.547100430962, " -[42] "804.065022775202, 931.340589597203, 934.837830059897, 788.422986194072, " -[43] "707.666678543854, 616.37838266375, 689.250456425465), .Dim = c(168L, " -[44] "3L), .Dimnames = list(NULL, c(\"structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, \", " -[45] "\"structure(c(419.147602949539, 391.474665943444, 435.919286153217, \", " -[46] "\"structure(c(484.030717075782, 462.954959541421, 526.353307750503, \"" -[47] ")), .Tsp = c(1949, 1962.91666666667, 12), class = c(\"mts\", \"ts\", " -[48] "\"matrix\"))" - +##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse35#Output.IgnoreWhitespace# +#cat({argv <- list(structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, 140, 145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166, 171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194, 196, 196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201, 204, 188, 235, 227, 234, 264, 302, 293, 259, 229, 203, 229, 242, 233, 267, 269, 270, 315, 364, 347, 312, 274, 237, 278, 284, 277, 317, 313, 318, 374, 413, 405, 355, 306, 271, 306, 315, 301, 356, 348, 355, 422, 465, 467, 404, 347, 305, 336, 340, 318, 362, 348, 363, 435, 491, 505, 404, 359, 310, 337, 360, 342, 406, 396, 420, 472, 548, 559, 463, 407, 362, 405, 417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390, 432, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 419.147602949539, 391.474665943444, 435.919286153217, 443.935203034261, 455.023399013445, 517.28707821144, 589.71337277669, 582.999919227301, 484.573388713116, 428.878182738437, 368.526582998452, 406.728709993152, 415.660571294428, 388.716535970235, 433.006017658935, 440.885684396326, 451.651900136866, 513.051252429496, 584.327164324967, 577.055407135124, 479.076505013118, 423.494870357491, 363.43932958967, 400.592058645117, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 484.030717075782, 462.954959541421, 526.353307750503, 546.165638262644, 569.502470928676, 657.838443307596, 761.241730163307, 763.280655335144, 642.989004951864, 576.423799567567, 501.429012064338, 559.981301364233, 591.700754553767, 565.210772316967, 642.377841008703, 666.682421047093, 695.547100430962, 804.065022775202, 931.340589597203, 934.837830059897, 788.422986194072, 707.666678543854, 616.37838266375, 689.250456425465), .Dim = c(168L, 3L), .Dimnames = list(NULL, c('structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, ', 'structure(c(419.147602949539, 391.474665943444, 435.919286153217, ', 'structure(c(484.030717075782, 462.954959541421, 526.353307750503, ')), .Tsp = c(1949, 1962.91666666667, 12), class = c('mts', 'ts', 'matrix')), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))}) +structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, 140, 145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166, 171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194, 196, 196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201, 204, 188, 235, 227, 234, 264, 302, 293, 259, 229, 203, 229, 242, 233, 267, 269, 270, 315, 364, 347, 312, 274, 237, 278, 284, 277, 317, 313, 318, 374, 413, 405, 355, 306, 271, 306, 315, 301, 356, 348, 355, 422, 465, 467, 404, 347, 305, 336, 340, 318, 362, 348, 363, 435, 491, 505, 404, 359, 310, 337, 360, 342, 406, 396, 420, 472, 548, 559, 463, 407, 362, 405, 417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390, 432, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 419.147602949539, 391.474665943444, 435.919286153217, 443.935203034261, 455.023399013445, 517.28707821144, 589.71337277669, 582.999919227301, 484.573388713116, 428.878182738437, 368.526582998452, 406.728709993152, 415.660571294428, 388.716535970235, 433.006017658935, 440.885684396326, 451.651900136866, 513.051252429496, 584.327164324967, 577.055407135124, 479.076505013118, 423.494870357491, 363.43932958967, 400.592058645117, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 484.030717075782, 462.954959541421, 526.353307750503, 546.165638262644, 569.502470928676, 657.838443307596, 761.241730163307, 763.280655335144, 642.989004951864, 576.423799567567, 501.429012064338, 559.981301364233, 591.700754553767, 565.210772316967, 642.377841008703, 666.682421047093, 695.547100430962, 804.065022775202, 931.340589597203, 934.837830059897, 788.422986194072, 707.666678543854, 616.37838266375, 689.250456425465), .Dim = c(168L, 3L), .Dimnames = list(NULL, c("structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, ", "structure(c(419.147602949539, 391.474665943444, 435.919286153217, ", "structure(c(484.030717075782, 462.954959541421, 526.353307750503, " )), .Tsp = c(1949, 1962.91666666667, 12), class = c("mts", "ts", "matrix")) ##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse36# #argv <- list(numeric(0), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) [1] "numeric(0)" @@ -16992,7 +17458,7 @@ a[a <- TRUE] #argv <- list(0:12, 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) [1] "0:12" -##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse38#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse38# #argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = structure('integer(0)', .Names = 'c0')), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) [1] "structure(list(c0 = structure(integer(0), .Label = character(0), class = \"factor\")), .Names = \"c0\", row.names = character(0), class = structure(\"integer(0)\", .Names = \"c0\"))" @@ -17004,7 +17470,7 @@ a[a <- TRUE] #argv <- list(quote(unclass(x)), 500, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) [1] "unclass(x)" -##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse40#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse40# #argv <- list(logical(0), logical(0), FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) [1] "logical(0)" Warning message: @@ -17023,11 +17489,9 @@ invalid 'cutoff' value for 'deparse', using default [1] "glm(formula = y ~ x, family = poisson(identity), start = c(1, " [2] " 0))" -##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse44#Ignored.Unknown# -#argv <- list(quote(lm(formula = 1000/MPG.city ~ Weight + Cylinders + Type + EngineSize + DriveTrain, data = Cars93)), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) -[1] "lm(formula = 1000/MPG.city ~ Weight + Cylinders + Type + EngineSize + " -[2] " DriveTrain, data = Cars93)" - +##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse44#Output.IgnoreWhitespace# +#cat({argv <- list(quote(lm(formula = 1000/MPG.city ~ Weight + Cylinders + Type + EngineSize + DriveTrain, data = Cars93)), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))}) +lm(formula = 1000/MPG.city ~ Weight + Cylinders + Type + EngineSize + DriveTrain, data = Cars93) ##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse45# #argv <- list(0.333333333333333, 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) [1] "0.333333333333333" @@ -17053,11 +17517,9 @@ invalid 'cutoff' value for 'deparse', using default #argv <- list(quote(5 * exp(-x)), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) [1] "5 * exp(-x)" -##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse7#Ignored.Unknown# -#argv <- list(quote(y ~ ((g1) * exp((log(g2/g1)) * (1 - exp(-k * (x - Ta)))/(1 - exp(-k * (Tb - Ta)))))), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) -[1] "y ~ ((g1) * exp((log(g2/g1)) * (1 - exp(-k * (x - Ta)))/(1 - " -[2] " exp(-k * (Tb - Ta)))))" - +##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse7#Output.IgnoreWhitespace# +#cat({argv <- list(quote(y ~ ((g1) * exp((log(g2/g1)) * (1 - exp(-k * (x - Ta)))/(1 - exp(-k * (Tb - Ta)))))), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))}) +y ~ ((g1) * exp((log(g2/g1)) * (1 - exp(-k * (x - Ta)))/(1 - exp(-k * (Tb - Ta))))) ##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse8# #argv <- list(quote(tt <- table(c(rep(0, 7), rep(1, 4), rep(5, 3)))), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) [1] "tt <- table(c(rep(0, 7), rep(1, 4), rep(5, 3)))" @@ -17066,6 +17528,2495 @@ invalid 'cutoff' value for 'deparse', using default #argv <- list(quote(utils::str), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) [1] "utils::str" +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ (x+1)*(x+2), c("x"), hessian=FALSE) +expression({ + .expr1 <- x + 1 + .expr2 <- x + 2 + .value <- .expr1 * .expr2 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- .expr2 + .expr1 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ (x+1)*(x+2), c("x"), hessian=TRUE) +expression({ + .expr1 <- x + 1 + .expr2 <- x + 2 + .value <- .expr1 * .expr2 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- .expr2 + .expr1 + .hessian[, "x", "x"] <- 1 + 1 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ (x+1)*(x+2*(x-1)), c("x"), hessian=FALSE) +expression({ + .expr1 <- x + 1 + .expr4 <- x + 2 * (x - 1) + .value <- .expr1 * .expr4 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- .expr4 + .expr1 * (1 + 2) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ (x+1)*(x+2*(x-1)), c("x"), hessian=TRUE) +expression({ + .expr1 <- x + 1 + .expr4 <- x + 2 * (x - 1) + .expr6 <- 1 + 2 + .value <- .expr1 * .expr4 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- .expr4 + .expr1 * .expr6 + .hessian[, "x", "x"] <- .expr6 + .expr6 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ (x+1)+(x+2), c("x"), hessian=FALSE) +expression({ + .value <- x + 1 + (x + 2) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 1 + 1 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ (x+1)+(x+2), c("x"), hessian=TRUE) +expression({ + .value <- x + 1 + (x + 2) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- 1 + 1 + .hessian[, "x", "x"] <- 0 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ (x+1)-(x+2), c("x"), hessian=FALSE) +expression({ + .value <- x + 1 - (x + 2) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 1 - 1 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ (x+1)-(x+2), c("x"), hessian=TRUE) +expression({ + .value <- x + 1 - (x + 2) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- 1 - 1 + .hessian[, "x", "x"] <- 0 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ (x+1)/(x+2), c("x"), hessian=FALSE) +expression({ + .expr1 <- x + 1 + .expr2 <- x + 2 + .value <- .expr1/.expr2 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 1/.expr2 - .expr1/.expr2^2 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#Output.IgnoreWhitespace# +#deriv(~ (x+1)/(x+2), c("x"), hessian=TRUE) +expression({ + .expr1 <- x + 1 + .expr2 <- x + 2 + .expr5 <- .expr2^2 + .expr8 <- 1/.expr5 + .value <- .expr1/.expr2 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- 1/.expr2 - .expr1/.expr5 + .hessian[, "x", "x"] <- -(.expr8 + (.expr8 - .expr1 * (2 * + .expr2)/.expr5^2)) + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#Ignored.OutputFormatting# +#deriv(~ (x+1)^(x+2), c("x"), hessian=FALSE) +expression({ + .expr1 <- x + 1 + .expr2 <- x + 2 + .expr3 <- .expr1^.expr2 + .value <- .expr3 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- .expr1^(.expr2 - 1) * .expr2 + .expr3 * log(.expr1) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ -(x+1)+(x+2), c("x"), hessian=FALSE) +expression({ + .value <- -(x + 1) + (x + 2) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 1 - 1 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ -(x+1)+(x+2), c("x"), hessian=TRUE) +expression({ + .value <- -(x + 1) + (x + 2) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- 1 - 1 + .hessian[, "x", "x"] <- 0 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ -(x+1)-(x+2), c("x"), hessian=FALSE) +expression({ + .value <- -(x + 1) - (x + 2) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- -(1 + 1) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ -(x+1)-(x+2), c("x"), hessian=TRUE) +expression({ + .value <- -(x + 1) - (x + 2) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- -(1 + 1) + .hessian[, "x", "x"] <- 0 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ 1, c("x"), hessian=FALSE) +expression({ + .value <- 1 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 0 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ 1, c("x"), hessian=TRUE) +expression({ + .value <- 1 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- 0 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ 2*x, c("x"), hessian=FALSE) +expression({ + .value <- 2 * x + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 2 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ 2*x, c("x"), hessian=TRUE) +expression({ + .value <- 2 * x + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- 2 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#Ignored.OutputFormatting# +#deriv(~ 2/x, c("x"), hessian=FALSE) +expression({ + .value <- 2/x + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- -(2/x^2) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ x+1, c("x"), hessian=FALSE) +expression({ + .value <- x + 1 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 1 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ x+1, c("x"), hessian=TRUE) +expression({ + .value <- x + 1 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- 1 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ x, c("x"), hessian=FALSE) +expression({ + .value <- x + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 1 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ x, c("x"), hessian=TRUE) +expression({ + .value <- x + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- 1 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ x/2, c("x"), hessian=FALSE) +expression({ + .value <- x/2 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 1/2 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ x/2, c("x"), hessian=TRUE) +expression({ + .value <- x/2 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- 1/2 + .hessian[, "x", "x"] <- 0 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ x^2, c("x"), hessian=FALSE) +expression({ + .value <- x^2 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 2 * x + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#deriv(~ x^2, c("x"), hessian=TRUE) +expression({ + .value <- x^2 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- 2 * x + .hessian[, "x", "x"] <- 2 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ (x+1)*(x+2), c("x"), hessian=FALSE); x<-0; eval(df) +[1] 2 +attr(,"gradient") + x +[1,] 3 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ (x+1)*(x+2), c("x"), hessian=TRUE); x<-0; eval(df) +[1] 2 +attr(,"gradient") + x +[1,] 3 +attr(,"hessian") +, , x + + x +[1,] 2 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ (x+1)*(x+2*(x-1)), c("x"), hessian=FALSE); x<-0; eval(df) +[1] -2 +attr(,"gradient") + x +[1,] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ (x+1)*(x+2*(x-1)), c("x"), hessian=TRUE); x<-0; eval(df) +[1] -2 +attr(,"gradient") + x +[1,] 1 +attr(,"hessian") +, , x + + x +[1,] 6 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ (x+1)+(x+2), c("x"), hessian=FALSE); x<-0; eval(df) +[1] 3 +attr(,"gradient") + x +[1,] 2 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ (x+1)+(x+2), c("x"), hessian=TRUE); x<-0; eval(df) +[1] 3 +attr(,"gradient") + x +[1,] 2 +attr(,"hessian") +, , x + + x +[1,] 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ (x+1)-(x+2), c("x"), hessian=FALSE); x<-0; eval(df) +[1] -1 +attr(,"gradient") + x +[1,] 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ (x+1)-(x+2), c("x"), hessian=TRUE); x<-0; eval(df) +[1] -1 +attr(,"gradient") + x +[1,] 0 +attr(,"hessian") +, , x + + x +[1,] 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ (x+1)/(x+2), c("x"), hessian=FALSE); x<-0; eval(df) +[1] 0.5 +attr(,"gradient") + x +[1,] 0.25 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ (x+1)/(x+2), c("x"), hessian=TRUE); x<-0; eval(df) +[1] 0.5 +attr(,"gradient") + x +[1,] 0.25 +attr(,"hessian") +, , x + + x +[1,] -0.25 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ (x+1)^(x+2), c("x"), hessian=FALSE); x<-0; eval(df) +[1] 1 +attr(,"gradient") + x +[1,] 2 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ -(x+1)+(x+2), c("x"), hessian=FALSE); x<-0; eval(df) +[1] 1 +attr(,"gradient") + x +[1,] 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ -(x+1)+(x+2), c("x"), hessian=TRUE); x<-0; eval(df) +[1] 1 +attr(,"gradient") + x +[1,] 0 +attr(,"hessian") +, , x + + x +[1,] 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ -(x+1)-(x+2), c("x"), hessian=FALSE); x<-0; eval(df) +[1] -3 +attr(,"gradient") + x +[1,] -2 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ -(x+1)-(x+2), c("x"), hessian=TRUE); x<-0; eval(df) +[1] -3 +attr(,"gradient") + x +[1,] -2 +attr(,"hessian") +, , x + + x +[1,] 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ 1, c("x"), hessian=FALSE); x<-0; eval(df) +[1] 1 +attr(,"gradient") + x +[1,] 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ 1, c("x"), hessian=TRUE); x<-0; eval(df) +[1] 1 +attr(,"gradient") + x +[1,] 0 +attr(,"hessian") +, , x + + x +[1,] 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ 2*x, c("x"), hessian=FALSE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 2 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ 2*x, c("x"), hessian=TRUE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 2 +attr(,"hessian") +, , x + + x +[1,] 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ 2/x, c("x"), hessian=FALSE); x<-0; eval(df) +[1] Inf +attr(,"gradient") + x +[1,] -Inf + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ x+1, c("x"), hessian=FALSE); x<-0; eval(df) +[1] 1 +attr(,"gradient") + x +[1,] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ x+1, c("x"), hessian=TRUE); x<-0; eval(df) +[1] 1 +attr(,"gradient") + x +[1,] 1 +attr(,"hessian") +, , x + + x +[1,] 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ x, c("x"), hessian=FALSE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ x, c("x"), hessian=TRUE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 1 +attr(,"hessian") +, , x + + x +[1,] 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ x/2, c("x"), hessian=FALSE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 0.5 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ x/2, c("x"), hessian=TRUE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 0.5 +attr(,"hessian") +, , x + + x +[1,] 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ x^2, c("x"), hessian=FALSE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1# +#df <- deriv(~ x^2, c("x"), hessian=TRUE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 0 +attr(,"hessian") +, , x + + x +[1,] 2 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#deriv(~ (x+1)*(y+2), c("x","y"), hessian=FALSE) +expression({ + .expr1 <- x + 1 + .expr2 <- y + 2 + .value <- .expr1 * .expr2 + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .grad[, "x"] <- .expr2 + .grad[, "y"] <- .expr1 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting# +#deriv(~ (x+1)*(y+2), c("x","y"), hessian=TRUE) +expression({ + .expr1 <- x + 1 + .expr2 <- y + 2 + .value <- .expr1 * .expr2 + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL, + c("x", "y"), c("x", "y"))) + .grad[, "x"] <- .expr2 + .hessian[, "x", "x"] <- 0 + .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- 1 + .grad[, "y"] <- .expr1 + .hessian[, "y", "y"] <- 0 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#deriv(~ (x+1)*(y+2*(x-1)), c("x","y"), hessian=FALSE) +expression({ + .expr1 <- x + 1 + .expr4 <- y + 2 * (x - 1) + .value <- .expr1 * .expr4 + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .grad[, "x"] <- .expr4 + .expr1 * 2 + .grad[, "y"] <- .expr1 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting# +#deriv(~ (x+1)*(y+2*(x-1)), c("x","y"), hessian=TRUE) +expression({ + .expr1 <- x + 1 + .expr4 <- y + 2 * (x - 1) + .value <- .expr1 * .expr4 + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL, + c("x", "y"), c("x", "y"))) + .grad[, "x"] <- .expr4 + .expr1 * 2 + .hessian[, "x", "x"] <- 2 + 2 + .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- 1 + .grad[, "y"] <- .expr1 + .hessian[, "y", "y"] <- 0 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#deriv(~ (x+1)-(y+2), c("x","y"), hessian=FALSE) +expression({ + .value <- x + 1 - (y + 2) + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .grad[, "x"] <- 1 + .grad[, "y"] <- -1 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#deriv(~ (x+1)-(y+2), c("x","y"), hessian=TRUE) +expression({ + .value <- x + 1 - (y + 2) + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL, + c("x", "y"), c("x", "y"))) + .grad[, "x"] <- 1 + .grad[, "y"] <- -1 + .hessian[, "y", "y"] <- 0 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting# +#deriv(~ (x+1)/(y+2), c("x","y"), hessian=FALSE) +expression({ + .expr1 <- x + 1 + .expr2 <- y + 2 + .value <- .expr1/.expr2 + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .grad[, "x"] <- 1/.expr2 + .grad[, "y"] <- -(.expr1/.expr2^2) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting# +#deriv(~ (x+1)/(y+2), c("x","y"), hessian=TRUE) +expression({ + .expr1 <- x + 1 + .expr2 <- y + 2 + .expr5 <- .expr2^2 + .value <- .expr1/.expr2 + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL, + c("x", "y"), c("x", "y"))) + .grad[, "x"] <- 1/.expr2 + .hessian[, "x", "x"] <- 0 + .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- -(1/.expr5) + .grad[, "y"] <- -(.expr1/.expr5) + .hessian[, "y", "y"] <- .expr1 * (2 * .expr2)/.expr5^2 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#deriv(~ (x+1)^(y+2), c("x","y"), hessian=FALSE) +expression({ + .expr1 <- x + 1 + .expr2 <- y + 2 + .expr3 <- .expr1^.expr2 + .value <- .expr3 + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .grad[, "x"] <- .expr1^(.expr2 - 1) * .expr2 + .grad[, "y"] <- .expr3 * log(.expr1) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting# +#deriv(~ (x+1)^(y+2), c("x","y"), hessian=TRUE) +expression({ + .expr1 <- x + 1 + .expr2 <- y + 2 + .expr3 <- .expr1^.expr2 + .expr4 <- .expr2 - 1 + .expr5 <- .expr1^.expr4 + .expr11 <- log(.expr1) + .expr15 <- .expr3 * .expr11 + .value <- .expr3 + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL, + c("x", "y"), c("x", "y"))) + .grad[, "x"] <- .expr5 * .expr2 + .hessian[, "x", "x"] <- .expr1^(.expr4 - 1) * .expr4 * .expr2 + .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- .expr5 * + .expr11 * .expr2 + .expr5 + .grad[, "y"] <- .expr15 + .hessian[, "y", "y"] <- .expr15 * .expr11 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#deriv(~ -(x+1)+(y+2), c("x","y"), hessian=FALSE) +expression({ + .value <- -(x + 1) + (y + 2) + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .grad[, "x"] <- -1 + .grad[, "y"] <- 1 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting# +#deriv(~ -(x+1)+(y+2), c("x","y"), hessian=TRUE) +expression({ + .value <- -(x + 1) + (y + 2) + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL, + c("x", "y"), c("x", "y"))) + .grad[, "x"] <- -1 + .hessian[, "x", "x"] <- 0 + .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- 0 + .grad[, "y"] <- 1 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#deriv(~ -(x+1)-(y+2), c("x","y"), hessian=FALSE) +expression({ + .expr5 <- -1 + .value <- -(x + 1) - (y + 2) + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .grad[, "x"] <- .expr5 + .grad[, "y"] <- .expr5 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting# +#deriv(~ -(x+1)-(y+2), c("x","y"), hessian=TRUE) +expression({ + .expr5 <- -1 + .value <- -(x + 1) - (y + 2) + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL, + c("x", "y"), c("x", "y"))) + .grad[, "x"] <- .expr5 + .hessian[, "x", "x"] <- 0 + .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- 0 + .grad[, "y"] <- .expr5 + .hessian[, "y", "y"] <- 0 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#deriv(~ 2*x*y, c("x","y"), hessian=FALSE) +expression({ + .expr1 <- 2 * x + .value <- .expr1 * y + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .grad[, "x"] <- 2 * y + .grad[, "y"] <- .expr1 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting# +#deriv(~ 2*x*y, c("x","y"), hessian=TRUE) +expression({ + .expr1 <- 2 * x + .value <- .expr1 * y + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL, + c("x", "y"), c("x", "y"))) + .grad[, "x"] <- 2 * y + .hessian[, "x", "x"] <- 0 + .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- 2 + .grad[, "y"] <- .expr1 + .hessian[, "y", "y"] <- 0 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting# +#deriv(~ 2/x*y, c("x","y"), hessian=FALSE) +expression({ + .expr1 <- 2/x + .value <- .expr1 * y + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .grad[, "x"] <- -(2/x^2 * y) + .grad[, "y"] <- .expr1 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting# +#deriv(~ 2/x*y, c("x","y"), hessian=TRUE) +expression({ + .expr1 <- 2/x + .expr3 <- x^2 + .expr4 <- 2/.expr3 + .value <- .expr1 * y + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL, + c("x", "y"), c("x", "y"))) + .grad[, "x"] <- -(.expr4 * y) + .hessian[, "x", "x"] <- 2 * (2 * x)/.expr3^2 * y + .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- -.expr4 + .grad[, "y"] <- .expr1 + .hessian[, "y", "y"] <- 0 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#deriv(~ x + y, c("x","y"), hessian=FALSE) +expression({ + .value <- x + y + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .grad[, "x"] <- 1 + .grad[, "y"] <- 1 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#deriv(~ x + y, c("x","y"), hessian=TRUE) +expression({ + .value <- x + y + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL, + c("x", "y"), c("x", "y"))) + .grad[, "x"] <- 1 + .grad[, "y"] <- 1 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#deriv(~ x*y, c("x","y"), hessian=FALSE) +expression({ + .value <- x * y + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .grad[, "x"] <- y + .grad[, "y"] <- x + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting# +#deriv(~ x*y, c("x","y"), hessian=TRUE) +expression({ + .value <- x * y + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL, + c("x", "y"), c("x", "y"))) + .grad[, "x"] <- y + .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- 1 + .grad[, "y"] <- x + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting# +#deriv(~ x/y/2, c("x","y"), hessian=FALSE) +expression({ + .value <- x/y/2 + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .grad[, "x"] <- 1/y/2 + .grad[, "y"] <- -(x/y^2/2) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting# +#deriv(~ x/y/2, c("x","y"), hessian=TRUE) +expression({ + .expr5 <- y^2 + .value <- x/y/2 + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL, + c("x", "y"), c("x", "y"))) + .grad[, "x"] <- 1/y/2 + .hessian[, "x", "x"] <- 0 + .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- -(1/.expr5/2) + .grad[, "y"] <- -(x/.expr5/2) + .hessian[, "y", "y"] <- x * (2 * y)/.expr5^2/2 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#deriv(~ x^y, c("x","y"), hessian=FALSE) +expression({ + .expr1 <- x^y + .value <- .expr1 + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .grad[, "x"] <- x^(y - 1) * y + .grad[, "y"] <- .expr1 * log(x) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting# +#deriv(~ x^y, c("x","y"), hessian=TRUE) +expression({ + .expr1 <- x^y + .expr2 <- y - 1 + .expr3 <- x^.expr2 + .expr9 <- log(x) + .expr13 <- .expr1 * .expr9 + .value <- .expr1 + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL, + c("x", "y"), c("x", "y"))) + .grad[, "x"] <- .expr3 * y + .hessian[, "x", "x"] <- x^(.expr2 - 1) * .expr2 * y + .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- .expr3 * + .expr9 * y + .expr3 + .grad[, "y"] <- .expr13 + .hessian[, "y", "y"] <- .expr13 * .expr9 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ (x+1)*(y+2), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df) +[1] 2 +attr(,"gradient") + x y +[1,] 2 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ (x+1)*(y+2), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df) +[1] 2 +attr(,"gradient") + x y +[1,] 2 1 +attr(,"hessian") +, , x + + x y +[1,] 0 1 + +, , y + + x y +[1,] 1 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ (x+1)*(y+2*(x-1)), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df) +[1] -2 +attr(,"gradient") + x y +[1,] 0 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ (x+1)*(y+2*(x-1)), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df) +[1] -2 +attr(,"gradient") + x y +[1,] 0 1 +attr(,"hessian") +, , x + + x y +[1,] 4 1 + +, , y + + x y +[1,] 1 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ (x+1)-(y+2), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df) +[1] -1 +attr(,"gradient") + x y +[1,] 1 -1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ (x+1)-(y+2), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df) +[1] -1 +attr(,"gradient") + x y +[1,] 1 -1 +attr(,"hessian") +, , x + + x y +[1,] 0 0 + +, , y + + x y +[1,] 0 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ (x+1)/(y+2), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df) +[1] 0.5 +attr(,"gradient") + x y +[1,] 0.5 -0.25 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ (x+1)/(y+2), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df) +[1] 0.5 +attr(,"gradient") + x y +[1,] 0.5 -0.25 +attr(,"hessian") +, , x + + x y +[1,] 0 -0.25 + +, , y + + x y +[1,] -0.25 0.25 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ (x+1)^(y+2), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df) +[1] 1 +attr(,"gradient") + x y +[1,] 2 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ (x+1)^(y+2), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df) +[1] 1 +attr(,"gradient") + x y +[1,] 2 0 +attr(,"hessian") +, , x + + x y +[1,] 2 1 + +, , y + + x y +[1,] 1 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ (x+1)^(y+2), c("x","y"), hessian=TRUE); x<-1; y<-1; eval(df) +[1] 8 +attr(,"gradient") + x y +[1,] 12 5.545177 +attr(,"hessian") +, , x + + x y +[1,] 12 12.31777 + +, , y + + x y +[1,] 12.31777 3.843624 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ -(x+1)+(y+2), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df) +[1] 1 +attr(,"gradient") + x y +[1,] -1 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ -(x+1)+(y+2), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df) +[1] 1 +attr(,"gradient") + x y +[1,] -1 1 +attr(,"hessian") +, , x + + x y +[1,] 0 0 + +, , y + + x y +[1,] 0 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ -(x+1)-(y+2), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df) +[1] -3 +attr(,"gradient") + x y +[1,] -1 -1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ -(x+1)-(y+2), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df) +[1] -3 +attr(,"gradient") + x y +[1,] -1 -1 +attr(,"hessian") +, , x + + x y +[1,] 0 0 + +, , y + + x y +[1,] 0 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ 2*x*y, c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df) +[1] 0 +attr(,"gradient") + x y +[1,] 0 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ 2*x*y, c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df) +[1] 0 +attr(,"gradient") + x y +[1,] 0 0 +attr(,"hessian") +, , x + + x y +[1,] 0 2 + +, , y + + x y +[1,] 2 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ 2/x*y, c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df) +[1] NaN +attr(,"gradient") + x y +[1,] NaN Inf + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ 2/x*y, c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df) +[1] NaN +attr(,"gradient") + x y +[1,] NaN Inf +attr(,"hessian") +, , x + + x y +[1,] NaN -Inf + +, , y + + x y +[1,] -Inf 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ x + y, c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df) +[1] 0 +attr(,"gradient") + x y +[1,] 1 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ x + y, c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df) +[1] 0 +attr(,"gradient") + x y +[1,] 1 1 +attr(,"hessian") +, , x + + x y +[1,] 0 0 + +, , y + + x y +[1,] 0 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ x*y, c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df) +[1] 0 +attr(,"gradient") + x y +[1,] 0 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ x*y, c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df) +[1] 0 +attr(,"gradient") + x y +[1,] 0 0 +attr(,"hessian") +, , x + + x y +[1,] 0 1 + +, , y + + x y +[1,] 1 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ x/y/2, c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df) +[1] NaN +attr(,"gradient") + x y +[1,] Inf NaN + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ x/y/2, c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df) +[1] NaN +attr(,"gradient") + x y +[1,] Inf NaN +attr(,"hessian") +, , x + + x y +[1,] 0 -Inf + +, , y + + x y +[1,] -Inf NaN + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ x^y, c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df) +[1] 1 +attr(,"gradient") + x y +[1,] NaN -Inf + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2# +#df <- deriv(~ x^y, c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df) +[1] 1 +attr(,"gradient") + x y +[1,] NaN -Inf +attr(,"hessian") +, , x + + x y +[1,] NaN NaN + +, , y + + x y +[1,] NaN Inf + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.OutputFormatting# +#deriv(~ acos(x), c("x"), hessian=FALSE) +expression({ + .value <- acos(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- -(1/sqrt(1 - x^2)) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ asin(x), c("x"), hessian=FALSE) +expression({ + .value <- asin(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 1/sqrt(1 - x^2) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ asin(x), c("x"), hessian=TRUE) +expression({ + .expr3 <- 1 - x^2 + .expr4 <- sqrt(.expr3) + .value <- asin(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- 1/.expr4 + .hessian[, "x", "x"] <- 0.5 * (2 * x * .expr3^-0.5)/.expr4^2 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ atan(x), c("x"), hessian=FALSE) +expression({ + .value <- atan(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 1/(1 + x^2) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.OutputFormatting# +#deriv(~ atan(x), c("x"), hessian=TRUE) +expression({ + .expr3 <- 1 + x^2 + .value <- atan(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- 1/.expr3 + .hessian[, "x", "x"] <- -(2 * x/.expr3^2) + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ cos(x), c("x"), hessian=FALSE) +expression({ + .value <- cos(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- -sin(x) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ cos(x), c("x"), hessian=TRUE) +expression({ + .expr1 <- cos(x) + .value <- .expr1 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- -sin(x) + .hessian[, "x", "x"] <- -.expr1 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ cosh(x), c("x"), hessian=FALSE) +expression({ + .value <- cosh(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- sinh(x) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ cosh(x), c("x"), hessian=TRUE) +expression({ + .expr1 <- cosh(x) + .value <- .expr1 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- sinh(x) + .hessian[, "x", "x"] <- .expr1 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ digamma(x), c("x"), hessian=FALSE) +expression({ + .value <- digamma(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- trigamma(x) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.OutputFormatting# +#deriv(~ dnorm(x), c("x"), hessian=FALSE) +expression({ + .expr1 <- dnorm(x) + .value <- .expr1 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- -(x * .expr1) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ exp(x), c("x"), hessian=FALSE) +expression({ + .expr1 <- exp(x) + .value <- .expr1 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- .expr1 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ exp(x), c("x"), hessian=TRUE) +expression({ + .expr1 <- exp(x) + .value <- .expr1 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- .expr1 + .hessian[, "x", "x"] <- .expr1 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ gamma(x), c("x"), hessian=FALSE) +expression({ + .expr1 <- gamma(x) + .value <- .expr1 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- .expr1 * digamma(x) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ lgamma(x), c("x"), hessian=FALSE) +expression({ + .value <- lgamma(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- digamma(x) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ log(x), c("x"), hessian=FALSE) +expression({ + .value <- log(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 1/x + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.OutputFormatting# +#deriv(~ log(x), c("x"), hessian=TRUE) +expression({ + .value <- log(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- 1/x + .hessian[, "x", "x"] <- -(1/x^2) + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ pnorm(x), c("x"), hessian=FALSE) +expression({ + .value <- pnorm(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- dnorm(x) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.OutputFormatting# +#deriv(~ pnorm(x), c("x"), hessian=TRUE) +expression({ + .expr2 <- dnorm(x) + .value <- pnorm(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- .expr2 + .hessian[, "x", "x"] <- -(x * .expr2) + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ psigamma(x), c("x"), hessian=FALSE) +expression({ + .value <- psigamma(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- psigamma(x, 1L) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ sin(x), c("x"), hessian=FALSE) +expression({ + .value <- sin(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- cos(x) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ sin(x), c("x"), hessian=TRUE) +expression({ + .expr1 <- sin(x) + .value <- .expr1 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- cos(x) + .hessian[, "x", "x"] <- -.expr1 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ sinh(x), c("x"), hessian=FALSE) +expression({ + .value <- sinh(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- cosh(x) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ sinh(x), c("x"), hessian=TRUE) +expression({ + .expr1 <- sinh(x) + .value <- .expr1 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- cosh(x) + .hessian[, "x", "x"] <- .expr1 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ sqrt(x), c("x"), hessian=FALSE) +expression({ + .value <- sqrt(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 0.5 * x^-0.5 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ sqrt(x), c("x"), hessian=TRUE) +expression({ + .value <- sqrt(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- 0.5 * x^-0.5 + .hessian[, "x", "x"] <- 0.5 * (-0.5 * x^-1.5) + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ tan(x), c("x"), hessian=FALSE) +expression({ + .value <- tan(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 1/cos(x)^2 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ tan(x), c("x"), hessian=TRUE) +expression({ + .expr2 <- cos(x) + .expr3 <- .expr2^2 + .value <- tan(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- 1/.expr3 + .hessian[, "x", "x"] <- 2 * (sin(x) * .expr2)/.expr3^2 + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ tanh(x), c("x"), hessian=FALSE) +expression({ + .value <- tanh(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 1/cosh(x)^2 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.OutputFormatting# +#deriv(~ tanh(x), c("x"), hessian=TRUE) +expression({ + .expr2 <- cosh(x) + .expr3 <- .expr2^2 + .value <- tanh(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- 1/.expr3 + .hessian[, "x", "x"] <- -(2 * (sinh(x) * .expr2)/.expr3^2) + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#deriv(~ trigamma(x), c("x"), hessian=FALSE) +expression({ + .value <- trigamma(x) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- psigamma(x, 2L) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ acos(x), c("x"), hessian=FALSE); x<-0; eval(df) +[1] 1.570796 +attr(,"gradient") + x +[1,] -1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ asin(x), c("x"), hessian=FALSE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ asin(x), c("x"), hessian=TRUE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 1 +attr(,"hessian") +, , x + + x +[1,] 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ atan(x), c("x"), hessian=FALSE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ atan(x), c("x"), hessian=TRUE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 1 +attr(,"hessian") +, , x + + x +[1,] 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ cos(x), c("x"), hessian=FALSE); x<-0; eval(df) +[1] 1 +attr(,"gradient") + x +[1,] 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ cos(x), c("x"), hessian=TRUE); x<-0; eval(df) +[1] 1 +attr(,"gradient") + x +[1,] 0 +attr(,"hessian") +, , x + + x +[1,] -1 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ cosh(x), c("x"), hessian=FALSE); x<-0; eval(df) +[1] 1 +attr(,"gradient") + x +[1,] 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ cosh(x), c("x"), hessian=TRUE); x<-0; eval(df) +[1] 1 +attr(,"gradient") + x +[1,] 0 +attr(,"hessian") +, , x + + x +[1,] 1 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.Unimplemented# +#df <- deriv(~ digamma(x), c("x"), hessian=FALSE); x<-0; eval(df) +[1] NaN +attr(,"gradient") + x +[1,] Inf +Warning message: +In digamma(x) : NaNs produced + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ dnorm(x), c("x"), hessian=FALSE); x<-0; eval(df) +[1] 0.3989423 +attr(,"gradient") + x +[1,] 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ exp(x), c("x"), hessian=FALSE); x<-0; eval(df) +[1] 1 +attr(,"gradient") + x +[1,] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ exp(x), c("x"), hessian=TRUE); x<-0; eval(df) +[1] 1 +attr(,"gradient") + x +[1,] 1 +attr(,"hessian") +, , x + + x +[1,] 1 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ gamma(x), c("x"), hessian=FALSE); x<-0; eval(df) +[1] NaN +attr(,"gradient") + x +[1,] NaN +Warning messages: +1: In gamma(x) : NaNs produced +2: In digamma(x) : NaNs produced + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ lgamma(x), c("x"), hessian=FALSE); x<-0.5; eval(df) +[1] 0.5723649 +attr(,"gradient") + x +[1,] -1.96351 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ log(x), c("x"), hessian=FALSE); x<-0; eval(df) +[1] -Inf +attr(,"gradient") + x +[1,] Inf + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ log(x), c("x"), hessian=TRUE); x<--1; eval(df) +[1] NaN +attr(,"gradient") + x +[1,] -1 +attr(,"hessian") +, , x + + x +[1,] -1 + +Warning message: +In log(x) : NaNs produced + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ log(x), c("x"), hessian=TRUE); x<-0; eval(df) +[1] -Inf +attr(,"gradient") + x +[1,] Inf +attr(,"hessian") +, , x + + x +[1,] -Inf + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ log(x), c("x"), hessian=TRUE); x<-1; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 1 +attr(,"hessian") +, , x + + x +[1,] -1 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ pnorm(x), c("x"), hessian=FALSE); x<-0; eval(df) +[1] 0.5 +attr(,"gradient") + x +[1,] 0.3989423 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ pnorm(x), c("x"), hessian=TRUE); x<-0; eval(df) +[1] 0.5 +attr(,"gradient") + x +[1,] 0.3989423 +attr(,"hessian") +, , x + + x +[1,] 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.Unimplemented# +#df <- deriv(~ psigamma(x), c("x"), hessian=FALSE); x<-0; eval(df) +[1] NaN +attr(,"gradient") + x +[1,] Inf +Warning message: +In psigamma(x) : NaNs produced + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ sin(x), c("x"), hessian=FALSE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ sin(x), c("x"), hessian=TRUE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 1 +attr(,"hessian") +, , x + + x +[1,] 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ sinh(x), c("x"), hessian=FALSE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ sinh(x), c("x"), hessian=TRUE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 1 +attr(,"hessian") +, , x + + x +[1,] 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ sqrt(x), c("x"), hessian=FALSE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] Inf + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ sqrt(x), c("x"), hessian=TRUE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] Inf +attr(,"hessian") +, , x + + x +[1,] -Inf + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ tan(x), c("x"), hessian=FALSE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ tan(x), c("x"), hessian=TRUE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 1 +attr(,"hessian") +, , x + + x +[1,] 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ tanh(x), c("x"), hessian=FALSE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ tanh(x), c("x"), hessian=TRUE); x<--1; eval(df) +[1] -0.7615942 +attr(,"gradient") + x +[1,] 0.4199743 +attr(,"hessian") +, , x + + x +[1,] 0.6397 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ tanh(x), c("x"), hessian=TRUE); x<-0; eval(df) +[1] 0 +attr(,"gradient") + x +[1,] 1 +attr(,"hessian") +, , x + + x +[1,] 0 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1# +#df <- deriv(~ tanh(x), c("x"), hessian=TRUE); x<-1; eval(df) +[1] 0.7615942 +attr(,"gradient") + x +[1,] 0.4199743 +attr(,"hessian") +, , x + + x +[1,] -0.6397 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.Unimplemented# +#df <- deriv(~ trigamma(x), c("x"), hessian=FALSE); x<-0; eval(df) +[1] Inf +attr(,"gradient") + x +[1,] NaN +Warning message: +In psigamma(x, 2L) : NaNs produced + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1# +#deriv(~ log(2*x), c("x"), hessian=FALSE) +expression({ + .expr1 <- 2 * x + .value <- log(.expr1) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 2/.expr1 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#Ignored.OutputFormatting# +#deriv(~ log(2*x), c("x"), hessian=TRUE) +expression({ + .expr1 <- 2 * x + .value <- log(.expr1) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- 2/.expr1 + .hessian[, "x", "x"] <- -(2 * 2/.expr1^2) + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1# +#deriv(~ log(sin(2*x)), c("x"), hessian=FALSE) +expression({ + .expr1 <- 2 * x + .expr2 <- sin(.expr1) + .value <- log(.expr2) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- cos(.expr1) * 2/.expr2 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#Output.IgnoreWhitespace# +#deriv(~ log(sin(2*x)), c("x"), hessian=TRUE) +expression({ + .expr1 <- 2 * x + .expr2 <- sin(.expr1) + .expr5 <- cos(.expr1) * 2 + .value <- log(.expr2) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL, + c("x"), c("x"))) + .grad[, "x"] <- .expr5/.expr2 + .hessian[, "x", "x"] <- -(.expr2 * 2 * 2/.expr2 + .expr5 * + .expr5/.expr2^2) + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#Output.IgnoreWhitespace# +#deriv(~ log(sin(2*x)*cos(x^2)), c("x"), hessian=FALSE) +expression({ + .expr1 <- 2 * x + .expr2 <- sin(.expr1) + .expr3 <- x^2 + .expr4 <- cos(.expr3) + .expr5 <- .expr2 * .expr4 + .value <- log(.expr5) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- (cos(.expr1) * 2 * .expr4 - .expr2 * (sin(.expr3) * + .expr1))/.expr5 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#Output.IgnoreWhitespace# +#deriv(~ pnorm(sin(2*x)^log(x+1)), c("x"), hessian=FALSE) +expression({ + .expr1 <- 2 * x + .expr2 <- sin(.expr1) + .expr3 <- x + 1 + .expr4 <- log(.expr3) + .expr5 <- .expr2^.expr4 + .value <- pnorm(.expr5) + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- dnorm(.expr5) * (.expr2^(.expr4 - 1) * (.expr4 * + (cos(.expr1) * 2)) + .expr5 * (log(.expr2) * (1/.expr3))) + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1# +#df <- deriv(~ log(2*x), c("x"), hessian=FALSE); x<-0; eval(df) +[1] -Inf +attr(,"gradient") + x +[1,] Inf + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1# +#df <- deriv(~ log(2*x), c("x"), hessian=TRUE); x<-0; eval(df) +[1] -Inf +attr(,"gradient") + x +[1,] Inf +attr(,"hessian") +, , x + + x +[1,] -Inf + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1# +#df <- deriv(~ log(sin(2*x)), c("x"), hessian=FALSE); x<-0; eval(df) +[1] -Inf +attr(,"gradient") + x +[1,] Inf + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1# +#df <- deriv(~ log(sin(2*x)), c("x"), hessian=TRUE); x<-0; eval(df) +[1] -Inf +attr(,"gradient") + x +[1,] Inf +attr(,"hessian") +, , x + + x +[1,] NaN + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1# +#df <- deriv(~ log(sin(2*x)*cos(x^2)), c("x"), hessian=FALSE); x<-0; eval(df) +[1] -Inf +attr(,"gradient") + x +[1,] Inf + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1# +#df <- deriv(~ pnorm(sin(2*x)^log(x+1)), c("x"), hessian=FALSE); x<-0; eval(df) +[1] 0.8413447 +attr(,"gradient") + x +[1,] NaN + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testFunctionGenereration#Output.IgnoreWhitespace# +#(df <- deriv(~x^2*sin(x), "x", function.arg=TRUE));df(0) +function (x) +{ + .expr1 <- x^2 + .expr2 <- sin(x) + .value <- .expr1 * .expr2 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 2 * x * .expr2 + .expr1 * cos(x) + attr(.value, "gradient") <- .grad + .value +} +[1] 0 +attr(,"gradient") + x +[1,] 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testFunctionGenereration#Output.IgnoreWhitespace# +#(df <- deriv(~x^2*sin(x), "x", function.arg=c("x")));df(0) +function (x) +{ + .expr1 <- x^2 + .expr2 <- sin(x) + .value <- .expr1 * .expr2 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 2 * x * .expr2 + .expr1 * cos(x) + attr(.value, "gradient") <- .grad + .value +} +[1] 0 +attr(,"gradient") + x +[1,] 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testFunctionGenereration#Output.IgnoreWhitespace# +#(df <- deriv(~x^2*sin(x), "x", function.arg=function(x=1){}));df(0) +function (x = 1) +{ + .expr1 <- x^2 + .expr2 <- sin(x) + .value <- .expr1 * .expr2 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 2 * x * .expr2 + .expr1 * cos(x) + attr(.value, "gradient") <- .grad + .value +} +[1] 0 +attr(,"gradient") + x +[1,] 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testLongExpression#Output.IgnoreWhitespace# +#deriv(~ (log(2*x)+sin(x))*cos(y^x*(exp(x)))*(x*y+x^y/(x+y+1)), c("x","y"), hessian=FALSE) +expression({ + .expr1 <- 2 * x + .expr4 <- log(.expr1) + sin(x) + .expr5 <- y^x + .expr6 <- exp(x) + .expr7 <- .expr5 * .expr6 + .expr8 <- cos(.expr7) + .expr9 <- .expr4 * .expr8 + .expr11 <- x^y + .expr13 <- x + y + 1 + .expr15 <- x * y + .expr11/.expr13 + .expr21 <- sin(.expr7) + .expr35 <- .expr11/.expr13^2 + .value <- .expr9 * .expr15 + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .grad[, "x"] <- ((2/.expr1 + cos(x)) * .expr8 - .expr4 * + (.expr21 * (.expr5 * log(y) * .expr6 + .expr7))) * .expr15 + + .expr9 * (y + (x^(y - 1) * y/.expr13 - .expr35)) + .grad[, "y"] <- .expr9 * (x + (.expr11 * log(x)/.expr13 - + .expr35)) - .expr4 * (.expr21 * (y^(x - 1) * x * .expr6)) * + .expr15 + attr(.value, "gradient") <- .grad + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testLongExpression#Ignored.OutputFormatting# +#deriv(~ (log(2*x)+sin(x))*cos(y^x*(exp(x)))*(x*y+x^y/(x+y+1)), c("x","y"), hessian=TRUE) +expression({ + .expr1 <- 2 * x + .expr3 <- sin(x) + .expr4 <- log(.expr1) + .expr3 + .expr5 <- y^x + .expr6 <- exp(x) + .expr7 <- .expr5 * .expr6 + .expr8 <- cos(.expr7) + .expr9 <- .expr4 * .expr8 + .expr11 <- x^y + .expr13 <- x + y + 1 + .expr15 <- x * y + .expr11/.expr13 + .expr19 <- 2/.expr1 + cos(x) + .expr21 <- sin(.expr7) + .expr22 <- log(y) + .expr23 <- .expr5 * .expr22 + .expr24 <- .expr23 * .expr6 + .expr25 <- .expr24 + .expr7 + .expr26 <- .expr21 * .expr25 + .expr28 <- .expr19 * .expr8 - .expr4 * .expr26 + .expr30 <- y - 1 + .expr31 <- x^.expr30 + .expr32 <- .expr31 * y + .expr34 <- .expr13^2 + .expr35 <- .expr11/.expr34 + .expr37 <- y + (.expr32/.expr13 - .expr35) + .expr40 <- .expr28 * .expr37 + .expr41 <- .expr19 * .expr26 + .expr66 <- .expr32/.expr34 + .expr71 <- .expr11 * (2 * .expr13)/.expr34^2 + .expr77 <- log(x) + .expr78 <- .expr11 * .expr77 + .expr81 <- x + (.expr78/.expr13 - .expr35) + .expr83 <- x - 1 + .expr85 <- y^.expr83 * x + .expr86 <- .expr85 * .expr6 + .expr87 <- .expr21 * .expr86 + .expr89 <- .expr8 * .expr86 + .expr108 <- .expr78/.expr34 + .expr109 <- .expr108 - .expr71 + .expr113 <- .expr4 * .expr87 + .expr125 <- .expr113 * .expr81 + .value <- .expr9 * .expr15 + .grad <- array(0, c(length(.value), 2L), list(NULL, c("x", + "y"))) + .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL, + c("x", "y"), c("x", "y"))) + .grad[, "x"] <- .expr28 * .expr15 + .expr9 * .expr37 + .hessian[, "x", "x"] <- .expr40 - (.expr41 + (.expr3 + 2 * + 2/.expr1^2) * .expr8 + (.expr41 + .expr4 * (.expr8 * + .expr25 * .expr25 + .expr21 * (.expr23 * .expr22 * .expr6 + + .expr24 + .expr25)))) * .expr15 + (.expr40 + .expr9 * + (x^(.expr30 - 1) * .expr30 * y/.expr13 - .expr66 - (.expr66 - + .expr71))) + .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- .expr28 * + .expr81 - (.expr19 * .expr87 + .expr4 * (.expr89 * .expr25 + + .expr21 * ((.expr85 * .expr22 + .expr5 * (1/y)) * .expr6 + + .expr86))) * .expr15 + (.expr9 * (1 + ((.expr31 * + .expr77 * y + .expr31)/.expr13 - .expr66 - .expr109)) - + .expr113 * .expr37) + .grad[, "y"] <- .expr9 * .expr81 - .expr113 * .expr15 + .hessian[, "y", "y"] <- .expr9 * (.expr78 * .expr77/.expr13 - + .expr108 - .expr109) - .expr125 - (.expr4 * (.expr89 * + .expr86 + .expr21 * (y^(.expr83 - 1) * .expr83 * x * + .expr6)) * .expr15 + .expr125) + attr(.value, "gradient") <- .grad + attr(.value, "hessian") <- .hessian + .value +}) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testLongExpression# +#df <- deriv(~ (log(2*x)+sin(x))*cos(y^x*(exp(x)))*(x*y+x^y/(x+y+1)), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df) +[1] -Inf +attr(,"gradient") + x y +[1,] NaN NaN + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testLongExpression# +#df <- deriv(~ (log(2*x)+sin(x))*cos(y^x*(exp(x)))*(x*y+x^y/(x+y+1)), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df) +[1] -Inf +attr(,"gradient") + x y +[1,] NaN NaN +attr(,"hessian") +, , x + + x y +[1,] NaN NaN + +, , y + + x y +[1,] NaN NaN + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testUnusualExprs# +#(df <- deriv(1, "x"));df(0) +expression({ + .value <- 1 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 0 + attr(.value, "gradient") <- .grad + .value +}) +Error in df(0) : argument "df1" is missing, with no default + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testUnusualExprs# +#(df <- deriv(expression(x^2*sin(x)), "x"));df(0) +expression({ + .expr1 <- x^2 + .expr2 <- sin(x) + .value <- .expr1 * .expr2 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 2 * x * .expr2 + .expr1 * cos(x) + attr(.value, "gradient") <- .grad + .value +}) +Error in df(0) : argument "df1" is missing, with no default + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testUnusualExprs# +#(df <- deriv(quote(x^2*sin(x)), "x"));df(0) +expression({ + .expr1 <- x^2 + .expr2 <- sin(x) + .value <- .expr1 * .expr2 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 2 * x * .expr2 + .expr1 * cos(x) + attr(.value, "gradient") <- .grad + .value +}) +Error in df(0) : argument "df1" is missing, with no default + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testUnusualExprs# +#g<-quote(x^2);(df <- deriv(g, "x"));df(0) +expression({ + .value <- x^2 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 2 * x + attr(.value, "gradient") <- .grad + .value +}) +Error in df(0) : argument "df1" is missing, with no default + +##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testUnusualExprs# +#x<-1;(df <- deriv(x, "x"));df(0) +expression({ + .value <- 1 + .grad <- array(0, c(length(.value), 1L), list(NULL, c("x"))) + .grad[, "x"] <- 0 + attr(.value, "gradient") <- .grad + .value +}) +Error in df(0) : argument "df1" is missing, with no default + ##com.oracle.truffle.r.test.builtins.TestBuiltin_det.testDet# #{ det(matrix(c(1,-3,4,-5),nrow=2)) } [1] 7 @@ -17129,7 +20080,7 @@ f is deprecated. Use convertY instead. See help(Deprecated) -##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn10#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn10# #argv <- list('x is neither a vector nor a matrix: using as.numeric(x)', quote(dotchart(table(infert$education)))); .Internal(.dfltWarn(argv[[1]], argv[[2]])) NULL Warning message: @@ -17145,14 +20096,14 @@ In package.skeleton("myTst", code_files = tmp) : file55711ba85492 are now renamed to z<name>.R -##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn12#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn12# #argv <- list('incomplete final line found by readTableHeader on foo4', quote(read.table('foo4', header = TRUE))); .Internal(.dfltWarn(argv[[1]], argv[[2]])) NULL Warning message: In read.table("foo4", header = TRUE) : incomplete final line found by readTableHeader on foo4 -##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn2#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn2# #argv <- list('bessel_y(2,nu=288.12): precision lost in result', quote(besselY(2, nu = nu <- seq(3, 300, len = 51)))); .Internal(.dfltWarn(argv[[1]], argv[[2]])) NULL Warning message: @@ -17165,7 +20116,7 @@ NULL Warning message: glm.fit: algorithm stopped at boundary value -##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn4#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn4# #argv <- list('header and col.names are of different lengths', quote(read.table('foo3', header = TRUE, col.names = letters[1:4]))); .Internal(.dfltWarn(argv[[1]], argv[[2]])) NULL Warning message: @@ -17185,7 +20136,7 @@ NULL Warning message: In log(ifelse(y == 0, 1, y/mu)) : NaNs produced -##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn7#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn7# #argv <- list('drop argument will be ignored', quote(`[.data.frame`(women, 'height', drop = FALSE))); .Internal(.dfltWarn(argv[[1]], argv[[2]])) NULL Warning message: @@ -17199,7 +20150,7 @@ Warning message: In predict.lm(object, newdata, se.fit, scale = residual.scale, type = ifelse(type == : prediction from a rank-deficient fit may be misleading -##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn9#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn9# #argv <- list('1 y value <= 0 omitted from logarithmic plot', quote(xy.coords(x, NULL, log = log))); .Internal(.dfltWarn(argv[[1]], argv[[2]])) NULL Warning message: @@ -19327,6 +22278,12 @@ Error in (function (x) : object 'y' not found #argv <- list();do.call('double', argv) numeric(0) +##com.oracle.truffle.r.test.builtins.TestBuiltin_dput.testdput#Output.IgnoreWhitespace# +#x <- structure(list(A = c(1L, 1L), B = structure(c(1L, 1L), .Label = c('G', 'D'), class = 'factor'), C = structure(c(1L, 1L), .Label = c('G', 'D'), class = 'factor')), .Names = c('A', 'B', 'C'), row.names = 1:2, class = 'data.frame'); dput(x) +structure(list(A = c(1L, 1L), B = structure(c(1L, 1L), .Label = c("G", +"D"), class = "factor"), C = structure(c(1L, 1L), .Label = c("G", +"D"), class = "factor")), .Names = c("A", "B", "C"), row.names = 1:2, class = "data.frame") + ##com.oracle.truffle.r.test.builtins.TestBuiltin_dput.testdput1# #argv <- list(logical(0), structure(1L, class = c('terminal', 'connection')), 69); .Internal(dput(argv[[1]], argv[[2]], argv[[3]])) logical(0) @@ -19347,7 +22304,7 @@ structure(numeric(0), .Dim = c(0L, 0L)) #argv <- list(NULL, structure(1L, class = c('terminal', 'connection')), 69); .Internal(dput(argv[[1]], argv[[2]], argv[[3]])) NULL -##com.oracle.truffle.r.test.builtins.TestBuiltin_dput.testdput6#Ignored.Unimplemented# +##com.oracle.truffle.r.test.builtins.TestBuiltin_dput.testdput6# #argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = structure('integer(0)', .Names = 'c0')), structure(1L, class = c('terminal', 'connection')), 69); .Internal(dput(argv[[1]], argv[[2]], argv[[3]])) structure(list(c0 = structure(integer(0), .Label = character(0), class = "factor")), .Names = "c0", row.names = character(0), class = structure("integer(0)", .Names = "c0")) @@ -19550,7 +22507,7 @@ logical(0) Error in duplicated.default(c(1, 2, 1), incomparables = function() 42) : cannot coerce type 'closure' to vector of type 'double' -##com.oracle.truffle.r.test.builtins.TestBuiltin_duplicated.testDuplicated#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_duplicated.testDuplicated# #{ duplicated(c(1,2,3,2), incomparables = c(2+6i)) } [1] FALSE FALSE FALSE FALSE Warning message: @@ -19561,7 +22518,7 @@ In duplicated.default(c(1, 2, 3, 2), incomparables = c(2 + (0+6i))) : #{ duplicated(c(1,2,3,4)) } [1] FALSE FALSE FALSE FALSE -##com.oracle.truffle.r.test.builtins.TestBuiltin_duplicated.testDuplicated#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_duplicated.testDuplicated# #{ duplicated(c(1L, 2L, 1L, 1L, 3L, 2L), incomparables = "cat") } [1] FALSE FALSE TRUE TRUE FALSE TRUE Warning message: @@ -19938,6 +22895,10 @@ Error in environment(e1) <- 3 : replacement object is not an environment Error in environment(f) <- new.env() : attempt to set an attribute on NULL +##com.oracle.truffle.r.test.builtins.TestBuiltin_environmentassign.testenvironmentassign1# +#{ f <- asS4(function(x) x+1); r <- isS4(f); environment(f) <- new.env(); r && isS4(f) } +[1] TRUE + ##com.oracle.truffle.r.test.builtins.TestBuiltin_environmentassign.testenvironmentassign1# #{ f <- function() x; f2 <- f; e <- new.env(); assign('x', 2, envir=e); x <- 1; environment(f) <- e; c(f(), f2())} [1] 2 1 @@ -19949,6 +22910,10 @@ Error in environment(f) <- new.env() : #{ f <- function() {}; environment(f) <- NULL } Error in environment(f) <- NULL : use of NULL environment is defunct +##com.oracle.truffle.r.test.builtins.TestBuiltin_environmentassign.testenvironmentassign1# +#{ jh <- function(x) x+1; attributes(jh) <- list(myMetaData ='hello'); environment(jh) <- new.env(); attr(jh, 'myMetaData') } +[1] "hello" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_eval.testEval# #eval('foo') [1] "foo" @@ -20045,6 +23010,11 @@ x #{ ne <- new.env(); evalq(x <- 1, ne); ls(ne) } [1] "x" +##com.oracle.truffle.r.test.builtins.TestBuiltin_eval.testReturnInEvalExpr# +#f1 <- function(x) { eval(quote(if(x>2){return()}else 1)); 10 };f1(5);f1(0) +[1] 10 +[1] 10 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_eval.testWithEnvirAndEnclose# #a <- 1; lang <- quote(list(a)); eval(lang, NULL, NULL) Error in eval(expr, envir, enclos) : object 'a' not found @@ -20121,7 +23091,7 @@ Error in exp() : 0 arguments passed to 'exp' which requires 1 [41] 6.221958e+21 2.421950e-01 1.309385e+01 3.972165e-01 7.452503e-03 [46] 9.494906e-01 1.450621e+00 2.421950e-01 2.346339e+19 -##com.oracle.truffle.r.test.builtins.TestBuiltin_exp.testexp11#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_exp.testexp11# #argv <- list(c(-745, -744, -743, -742, -741, -740, -730, -720, -710, -709, -708, -707, -706, -705));exp(argv[[1]]); [1] 4.940656e-324 9.881313e-324 1.976263e-323 5.434722e-323 1.531604e-322 [6] 4.199558e-322 9.226315e-318 2.032231e-313 4.476286e-309 1.216781e-308 @@ -20259,7 +23229,7 @@ numeric(0) #{ fr <- data.frame(1:3,4:6); attr(fr,'names') <- c(NA,'col'); fr[1,2] } [1] 4 -##com.oracle.truffle.r.test.builtins.TestBuiltin_extract_dataframe.extractDataFrameWithNULLNames#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_extract_dataframe.extractDataFrameWithNULLNames# #{ fr <- data.frame(1:3,4:6); attr(fr,'names') <- NULL; fr['col'] } 1 NULL @@ -20672,6 +23642,14 @@ Levels: A B C D E #tmp <- c(1,8,NA,3); pivot <- c(1,2,4,3); tmp[pivot] <- tmp; tmp [1] 1 8 3 NA +##com.oracle.truffle.r.test.builtins.TestBuiltin_extract_replace.replaceExpressionInLanguage#Ignored.OutputFormatting# +#e1 <- expression(x^2); l1 <- quote(y^2); l1[1] <- e1; l1 +(x^2)(y, 2) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_extract_replace.replaceExpressionInLanguage# +#e1 <- expression(x^2); l1 <- quote(y^2); l1[1] <- e1; l1[[1]]==e1[[1]] +[1] TRUE + ##com.oracle.truffle.r.test.builtins.TestBuiltin_extract_replace.replaceInLanguagePreservesAttributes# #f <- quote(a+b); attr(f, 'mya') <- 42; f[[2]] <- quote(q); f q + b @@ -20710,12 +23688,12 @@ logical(0) #{ x <- factor(c("a", "b", "a")); levels(x)<-c(7, 42); is.character(levels(x)) } [1] TRUE -##com.oracle.truffle.r.test.builtins.TestBuiltin_factor.testFactor#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_factor.testFactor# #{ x<-c("1","2","3"); class(x)<-"factor"; x } Error in class(x) <- "factor" : adding class "factor" to an invalid object -##com.oracle.truffle.r.test.builtins.TestBuiltin_factor.testFactor#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_factor.testFactor# #{ x<-c(1,2,3); class(x)<-"factor"; x } Error in class(x) <- "factor" : adding class "factor" to an invalid object @@ -20888,7 +23866,7 @@ In Ops.ordered(x, "a") : '+' is not meaningful for ordered factors #{ x<-factor(c("a", "b", "a", "c")); x == c("a", "b") } [1] TRUE TRUE TRUE FALSE -##com.oracle.truffle.r.test.builtins.TestBuiltin_factor.testFactor#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_factor.testFactor# #{ x<-factor(c("c", "b", "a", "c")); y<-c(1); y[1]<-x; y } [1] 3 Warning message: @@ -20899,7 +23877,7 @@ In y[1] <- x : #{ x<-factor(c("c", "b", "a", "c")); y<-c(1); y[[1]]<-x; y } Error in y[[1]] <- x : more elements supplied than there are to replace -##com.oracle.truffle.r.test.builtins.TestBuiltin_factor.testFactor#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_factor.testFactor# #{ x<-factor(c("c", "b", "a", "c")); y<-list(1); y[1]<-x; y } [[1]] [1] 3 @@ -21060,11 +24038,11 @@ logical(0) #argv <- list(character(0)); .Internal(file.exists(argv[[1]])) logical(0) -##com.oracle.truffle.r.test.builtins.TestBuiltin_fileinfo.testfileinfo1#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_fileinfo.testfileinfo1# #argv <- list('/home/lzhao/hg/r-instrumented/library/codetools/data'); .Internal(file.info(argv[[1]])) Error: 1 argument passed to .Internal(file.info) which requires 2 -##com.oracle.truffle.r.test.builtins.TestBuiltin_fileinfo.testfileinfo2#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_fileinfo.testfileinfo2# #argv <- list(character(0)); .Internal(file.info(argv[[1]])) Error: 1 argument passed to .Internal(file.info) which requires 2 @@ -21259,7 +24237,7 @@ NULL #argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = 'data.frame')); .Internal(formals(argv[[1]])) NULL -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat1#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat1#Output.IgnoreErrorMessage# #argv <- list(structure(c(0, 72.7, 56.4, 72.7, 0, 63.3, 56.4, 63.3, 0), .Dim = c(3L, 3L), .Dimnames = list(c('Girth', 'Height', 'Volume'), c('Girth', 'Height', 'Volume'))), FALSE, 7L, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]], , argv[[9]])) Error in .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], : argument 10 is empty @@ -21274,7 +24252,7 @@ Error in .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], : 1 2 <NA> "1" "2" "1" -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat12#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat12# #argv <- list(c('Min.', '1st Qu.', 'Median', 'Mean', '3rd Qu.', 'Max.'), FALSE, NULL, 0L, NULL, 0L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] "Min. " "1st Qu." "Median " "Mean " "3rd Qu." "Max. " @@ -21282,12 +24260,12 @@ Error in .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], : #argv <- list(c(1L, 2L, 3L, 4L, 5L, -1L, -2L), FALSE, NULL, 0L, NULL, 3L, FALSE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] " 1" " 2" " 3" " 4" " 5" "-1" "-2" -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat14#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat14# #argv <- list(structure(c(NA, 1, 1, 1), .Names = c('<none>', '- x4', '- x2', '- x1')), FALSE, 5L, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) <none> - x4 - x2 - x1 "NA" " 1" " 1" " 1" -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat15#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat15# #argv <- list(2.22044604925031e-16, FALSE, 1, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] "2e-16" @@ -21316,11 +24294,11 @@ Error in argv[[9]] : subscript out of bounds #argv <- list(c('abc', NA, 'def'), FALSE, NULL, 0L, NULL, 3L, FALSE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] "abc" NA "def" -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat23#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat23# #argv <- list(c(NA, 2L, 4L, 7L), FALSE, NULL, 0L, NULL, 3L, FALSE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] "NA" " 2" " 4" " 7" -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat24#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat24# #argv <- list(c(1.1+0i, NA, 3+0i), FALSE, NULL, 0L, NULL, 3L, FALSE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] "1.1+0i" " NA" "3.0+0i" @@ -21332,7 +24310,7 @@ Error in argv[[9]] : subscript out of bounds #argv <- list(c(172, 88, 88, 55, 92, 92, 72, 72, 63, 63), TRUE, NULL, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] "172" "88" "88" "55" "92" "92" "72" "72" "63" "63" -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat27#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat27# #argv <- list(structure(c(142L, 104L, 71L, 250L), .Dim = 4L, .Dimnames = structure(list(c('(1) Approve STRONGLY', '(2) Approve SOMEWHAT', '(3) Disapprove SOMEWHAT', '(4) Disapprove STRONGLY')), .Names = '')), FALSE, 7L, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) (1) Approve STRONGLY (2) Approve SOMEWHAT (3) Disapprove SOMEWHAT @@ -21340,11 +24318,11 @@ Error in argv[[9]] : subscript out of bounds (4) Disapprove STRONGLY "250" -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat28#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat28# #argv <- list(structure(c('***', '*', ' ', ' ', ' '), legend = '0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1', class = 'noquote'), FALSE, NULL, 0L, NULL, 0L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] "***" "* " " " " " " " -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat29#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat29# #argv <- list(structure(c(0, 5, 118, 57, 0, 1, 4, 140, 0, 11, 154, 14, 0, 13, 13, 80, 35, 13, 387, 75, 17, 14, 89, 76, 0, 0, 670, 192, 0, 0, 3, 20), .Dim = c(1L, 32L), row.vars = structure(list(), .Names = character(0)), col.vars = structure(list(Class = c('1st', '2nd', '3rd', 'Crew'), Sex = c('Male', 'Female'), Age = c('Child', 'Adult'), Survived = c('No', 'Yes')), .Names = c('Class', 'Sex', 'Age', 'Survived'))), FALSE, 7L, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [1,] " 0" " 5" "118" " 57" " 0" " 1" " 4" "140" " 0" " 11" "154" " 14" @@ -21353,11 +24331,11 @@ Error in argv[[9]] : subscript out of bounds [,25] [,26] [,27] [,28] [,29] [,30] [,31] [,32] [1,] " 0" " 0" "670" "192" " 0" " 0" " 3" " 20" -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat3#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat3# #argv <- list(c('Inf', '-Inf', 'NaN', 'NA'), FALSE, NULL, 0L, 4, 1L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] " Inf" "-Inf" " NaN" " NA" -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat30#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat30# #argv <- list(c('', '', '\'Adult\'', '\'No\'', '', '387'), FALSE, NULL, 0L, NULL, 1L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] " " " " "'Adult'" " 'No'" " " " 387" @@ -21365,7 +24343,7 @@ Error in argv[[9]] : subscript out of bounds #argv <- list(2.2250738585072e-308, TRUE, NULL, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] "2.225074e-308" -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat32#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat32# #argv <- list(c(-0.318309886183791+0i, 0-0.564189583547756i, 1+0i, 0+1.77245385090552i, -3.14159265358979+0i), TRUE, 2, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] "-0.32+0.00i" "0.00-0.56i" "1.00+0.00i" "0.00+1.77i" "-3.14+0.00i" @@ -21403,7 +24381,7 @@ Error in argv[[9]] : subscript out of bounds #argv <- list(structure(integer(0), .Label = character(0), class = 'factor'), TRUE, NULL, 0L, NULL, 3L, FALSE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) character(0) -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat37#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat37# #argv <- list(structure(c(213198964, 652424.52183908), .Names = c('null.deviance', 'deviance')), FALSE, 5L, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) null.deviance deviance "213198964" " 652425" @@ -21417,7 +24395,7 @@ null.deviance deviance #argv <- list(FALSE, FALSE, NULL, 0L, NULL, 3L, FALSE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] "FALSE" -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat4#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat4# #argv <- list(structure(c('axx', 'b', 'c', 'd', 'e', 'f', 'g', 'h'), .Dim = c(2L, 4L)), FALSE, NULL, 0L, NULL, 1L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [,1] [,2] [,3] [,4] [1,] "axx" " c" " e" " g" @@ -21438,11 +24416,11 @@ null.deviance deviance [61] "3084" "2605" "2573" "2143" "1693" "1504" "1461" "1354" "1333" "1492" [71] "1781" "1915" -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat42#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat42# #argv <- list(c(2.5, 97.5), TRUE, 3, 0L, NULL, 3L, TRUE, FALSE, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] "2.5" "97.5" -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat43#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat43# #argv <- list(structure(c(9.4, 10.2, 9.2, 4.4, 3.5, 2.7), .Dim = c(3L, 2L), .Dimnames = list(NULL, c('Estimate', 'Std.Err'))), FALSE, 2, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) Estimate Std.Err [1,] " 9.4" " 4.4" @@ -21457,7 +24435,7 @@ null.deviance deviance #argv <- list(1.2e+07, FALSE, NULL, 9L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] "1.2e+07" -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat47#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat47# #argv <- list(-0.01234+3.14159265358979i, FALSE, NULL, 14L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] "-0.01234000000000+3.14159265358979i" @@ -21465,7 +24443,7 @@ null.deviance deviance #argv <- list(c(TRUE, FALSE, TRUE, FALSE, FALSE, FALSE), FALSE, NULL, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] " TRUE" "FALSE" " TRUE" "FALSE" "FALSE" "FALSE" -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat49#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat49# #argv <- list(3.141, FALSE, NULL, 13L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] "3.1410000000000" @@ -21498,7 +24476,7 @@ null.deviance deviance #argv <- list(1e-11, FALSE, NULL, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] "1e-11" -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat56#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat56# #argv <- structure(list(x = 0.04, digits = 3, nsmall = 3), .Names = c('x', 'digits', 'nsmall'));do.call('format', argv) [1] "0.040" @@ -21511,7 +24489,7 @@ null.deviance deviance <none> - x4 - x2 - x1 " 47.97" " 57.90" " 74.76" "868.88" -##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat7#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat7# #argv <- list(c('a', 'NA', NA, 'b'), FALSE, NULL, 0L, NULL, 0L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [1] "a " "NA" "NA" "b " @@ -21539,11 +24517,11 @@ character(0) #argv <- list(c(0, 25, 50, 75, 100), 'double', 1, 6L, 'fg', '', c(14L, 13L, 13L, 13L, 13L)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]])) [1] "0" "25" "50" "75" "100" -##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC12#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC12# #argv <- list(5L, 'integer', 2, 2L, 'd', '', 10L); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]])) [1] " 5" -##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC13#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC13# #argv <- list(c(3.14159265358979e-05, 0.000314159265358979, 0.00314159265358979, 0.0314159265358979, 0.314159265358979, 3.14159265358979, 31.4159265358979, 314.159265358979, 3141.59265358979, 31415.9265358979), 'double', 5, 4, 'fg', '', c(15, 14, 13, 12, 11, 10, 9, 9, 9, 9)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]])) [1] "0.00003142" "0.0003142" "0.003142" "0.03142" "0.3142" [6] "3.142" "31.42" "314.2" " 3142" "31416" @@ -21571,7 +24549,7 @@ character(0) #argv <- list(c(-3, -2, -1, 0, 1, 2, 3), 'double', 1L, 4L, 'g', '', c(12L, 12L, 12L, 12L, 12L, 12L, 12L)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]])) [1] "-3" "-2" "-1" "0" "1" "2" "3" -##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC6#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC6# #argv <- list(3L, 'integer', 3, 2L, 'd', '0', 10L); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]])) [1] "003" @@ -21579,7 +24557,7 @@ character(0) #argv <- list(c(0, 25, 50, 75, 100), 'double', 1, 7L, 'fg', '', c(16L, 15L, 15L, 15L, 15L)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]])) [1] "0" "25" "50" "75" "100" -##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC8#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC8# #argv <- list(structure(48.4333681840033, .Names = 'value'), 'double', 5L, 4L, 'g', '', 12L); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]])) [1] "48.43" @@ -21696,7 +24674,7 @@ character(0) #argv <- list(712L, NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]])) [1] 3 -##com.oracle.truffle.r.test.builtins.TestBuiltin_formatpval.testformatpval1#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_formatpval.testformatpval1# #argv <- structure(list(pv = 0.200965994008331, digits = 3), .Names = c('pv', 'digits'));do.call('format.pval', argv) [1] "0.201" @@ -21704,14 +24682,14 @@ character(0) #argv <- list(1);g(argv[[1]]); Error: could not find function "g" -##com.oracle.truffle.r.test.builtins.TestBuiltin_gamma.testgamma1#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_gamma.testgamma1# #argv <- list(c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1));gamma(argv[[1]]); [1] NaN 9.513508 4.590844 2.991569 2.218160 1.772454 1.489192 1.298055 [9] 1.164230 1.068629 1.000000 Warning message: In gamma(argv[[1]]) : NaNs produced -##com.oracle.truffle.r.test.builtins.TestBuiltin_gamma.testgamma2#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_gamma.testgamma2# #argv <- list(FALSE);gamma(argv[[1]]); [1] NaN Warning message: @@ -21721,11 +24699,11 @@ In gamma(argv[[1]]) : NaNs produced #argv <- list(structure(numeric(0), .Dim = c(0L, 0L)));gamma(argv[[1]]); <0 x 0 matrix> -##com.oracle.truffle.r.test.builtins.TestBuiltin_gamma.testgamma5#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_gamma.testgamma5# #argv <- list(101);gamma(argv[[1]]); [1] 9.332622e+157 -##com.oracle.truffle.r.test.builtins.TestBuiltin_gamma.testgamma6#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_gamma.testgamma6# #argv <- list(c(-3.000001, -3, -3, -2.999999, -2.965, -2.93, -2.895, -2.86, -2.825, -2.79, -2.755, -2.72, -2.685, -2.65, -2.615, -2.58, -2.545, -2.51, -2.475, -2.44, -2.405, -2.37, -2.335, -2.3, -2.265, -2.23, -2.195, -2.16, -2.125, -2.09, -2.055, -2.02, -2.000001, -2, -1.999999, -1.985, -1.95, -1.915, -1.88, -1.845, -1.81, -1.775, -1.74, -1.705, -1.67, -1.635, -1.6, -1.565, -1.53, -1.495, -1.46, -1.425, -1.39, -1.355, -1.32, -1.285, -1.25, -1.215, -1.18, -1.145, -1.11, -1.075, -1.04, -1.005, -1.000001, -1, -0.999999, -0.97, -0.935, -0.9, -0.865, -0.83, -0.795, -0.76, -0.725, -0.69, -0.655, -0.62, -0.585, -0.55, -0.515, -0.48, -0.445, -0.41, -0.375, -0.34, -0.305, -0.27, -0.235, -0.2, -0.165, -0.13, -0.0949999999999998, -0.0599999999999996, -0.0249999999999999, -1e-06, 0, 1e-06, 0.0100000000000002, 0.0450000000000004, 0.0800000000000001, 0.115, 0.15, 0.185, 0.22, 0.255, 0.29, 0.325, 0.36, 0.395, 0.43, 0.465, 0.5, 0.535, 0.57, 0.605, 0.640000000000001, 0.675, 0.71, 0.745000000000001, 0.78, 0.815, 0.850000000000001, 0.885, 0.92, 0.955000000000001, 0.99, 1.025, 1.06, 1.095, 1.13, 1.165, 1.2, 1.235, 1.27, 1.305, 1.34, 1.375, 1.41, 1.445, 1.48, 1.515, 1.55, 1.585, 1.62, 1.655, 1.69, 1.725, 1.76, 1.795, 1.83, 1.865, 1.9, 1.935, 1.97, 2.005, 2.04, 2.075, 2.11, 2.145, 2.18, 2.215, 2.25, 2.285, 2.32, 2.355, 2.39, 2.425, 2.46, 2.495, 2.53, 2.565, 2.6, 2.635, 2.67, 2.705, 2.74, 2.775, 2.81, 2.845, 2.88, 2.915, 2.95, 2.985, 3.02, 3.055, 3.09, 3.125, 3.16, 3.195, 3.23, 3.265, 3.3, 3.335, 3.37, 3.405, 3.44, 3.475, 3.51, 3.545, 3.58, 3.615, 3.65, 3.685, 3.72, 3.755, 3.79, 3.825, 3.86, 3.895, 3.93, 3.965, 4));gamma(argv[[1]]); [1] 1.666665e+05 NaN NaN -1.666669e+05 -4.985099e+00 [6] -2.619025e+00 -1.841442e+00 -1.462054e+00 -1.242971e+00 -1.105073e+00 @@ -22453,6 +25431,10 @@ integer(0) #argv <- list('^[[:blank:]]*$', 'mtext(\'«Latin-1 accented chars»: éè øØ å<Å æ<Æ\', side = 3)', FALSE, FALSE, FALSE, FALSE, FALSE, FALSE); .Internal(grep(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]])) integer(0) +##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testgrep13# +#argv <- list('.__T__[[<-:', '.__T__[[<-:base', FALSE, FALSE, FALSE, TRUE, FALSE, FALSE); .Internal(grep(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]])) +[1] 1 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testgrep2# #argv <- list('éè', '«Latin-1 accented chars»: éè øØ å<Å æ<Æ é éè', TRUE, FALSE, TRUE, FALSE, FALSE, FALSE); .Internal(grep(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]])) [1] 1 @@ -22600,7 +25582,7 @@ Error: invalid 'pattern' argument #{ gsub("a","aa", "prAgue alley", fixed=TRUE) } [1] "prAgue aalley" -##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub# #{ gsub("a","aa", "prAgue alley", fixed=TRUE, ignore.case=TRUE) } [1] "prAgue aalley" Warning message: @@ -23537,7 +26519,7 @@ attr(,"Rd_tag") #{x <- 10;class(x) <- c("a", "b"); inherits(x,"a") ;} [1] TRUE -##com.oracle.truffle.r.test.builtins.TestBuiltin_inherits.testInherits#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_inherits.testInherits# #{x <- 10;class(x) <- c("a", "b");inherits(x, "a", 1) ;} Error in inherits(x, "a", 1) : 'which' must be a length 1 logical vector @@ -23549,7 +26531,7 @@ Error in inherits(x, "a", 1) : 'which' must be a length 1 logical vector #{x <- 10;class(x) <- c("a", "b");inherits(x, "a", c(TRUE)) ;} [1] 1 -##com.oracle.truffle.r.test.builtins.TestBuiltin_inherits.testInherits#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_inherits.testInherits# #{x <- 10;class(x) <- c("a", "b");inherits(x, 2, c(TRUE)) ;} Error in inherits(x, 2, c(TRUE)) : 'what' must be a character vector @@ -23702,7 +26684,7 @@ Error in inherits(x, 2, c(TRUE)) : 'what' must be a character vector [1] 01 01 00 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [26] 00 00 00 00 00 00 00 -##com.oracle.truffle.r.test.builtins.TestBuiltin_intToBits.testintToBits#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_intToBits.testintToBits# #intToBits('23rrff') [1] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [26] 00 00 00 00 00 00 01 @@ -23743,7 +26725,7 @@ Error in intToBits() : argument "x" is missing, with no default [1] 00 01 00 00 01 00 00 00 01 00 00 01 00 00 01 01 01 01 00 00 00 01 00 00 00 [26] 00 00 00 00 00 00 00 -##com.oracle.truffle.r.test.builtins.TestBuiltin_intToBits.testintToBits#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_intToBits.testintToBits# #intToBits(5+7i) [1] 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [26] 00 00 00 00 00 00 00 @@ -23803,7 +26785,7 @@ raw(0) [101] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [126] 00 00 00 -##com.oracle.truffle.r.test.builtins.TestBuiltin_intToBits.testintToBits#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_intToBits.testintToBits# #intToBits(list(c(5,5,7,8),88,6L)) Error in intToBits(list(c(5, 5, 7, 8), 88, 6L)) : (list) object cannot be coerced to type 'integer' @@ -24902,7 +27884,7 @@ Error: object 'f' not found #{is.factor(c)} [1] FALSE -##com.oracle.truffle.r.test.builtins.TestBuiltin_isfactor.testIsFactor#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isfactor.testIsFactor# #{x<-1;class(x)<-"factor";is.factor(x)} Error in class(x) <- "factor" : adding class "factor" to an invalid object @@ -24981,7 +27963,7 @@ Error in class(x) <- "factor" : #argv <- list(c(20.1635649375266, 0.00464806897188935, 7.66871331765456, 12.5627629785965, 11.5797681339384, 12.9719582729673, 25.2769526097163, -1.81739378653632, 0.81215865601413, -3.83170645669318, -0.246853801421158, 3.46135095276697, 2.4554639832607, -3.21187324485145, -3.0183971859156));is.finite(argv[[1]]); [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE -##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite10#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite10# #argv <- list(structure(c(-32.6915744137254, -24.6945405669482, -24.6945405669482, -357.79068676373), .Dim = c(2L, 2L)));is.finite(argv[[1]]); [,1] [,2] [1,] TRUE TRUE @@ -24995,7 +27977,7 @@ Error in class(x) <- "factor" : #argv <- list(c(0.0599, 0.00599, 0.000599, 5.99e-05, 5.99e-06, 5.99e-07));is.finite(argv[[1]]); [1] TRUE TRUE TRUE TRUE TRUE TRUE -##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite13#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite13# #argv <- list(structure(c(-0.560475646552213+0i, 0.7424437487+0.205661411508856i, 1.39139505579429-0.26763356813179i, 0.928710764113827-0.221714979045717i, -0.46926798541295+1.18846175213664i, 0.7424437487-0.205661411508856i, 0.460916205989202+0i, -0.452623703774585+0.170604003753717i, -0.094501186832143+0.54302538277632i, -0.331818442379127+0.612232958468282i, 1.39139505579429+0.26763356813179i, -0.452623703774585-0.170604003753717i, 0.400771450594052+0i, -0.927967220342259+0.479716843914174i, -0.790922791530657+0.043092176305418i, 0.928710764113827+0.221714979045717i, -0.094501186832143-0.54302538277632i, -0.927967220342259-0.479716843914174i, 0.701355901563686+0i, -0.600841318509537+0.213998439984336i, -0.46926798541295-1.18846175213664i, -0.331818442379127-0.612232958468282i, -0.790922791530657-0.043092176305418i, -0.600841318509537-0.213998439984336i, -0.625039267849257+0i), .Dim = c(5L, 5L)));is.finite(argv[[1]]); [,1] [,2] [,3] [,4] [,5] [1,] TRUE TRUE TRUE TRUE TRUE @@ -25012,7 +27994,7 @@ Error in class(x) <- "factor" : #argv <- list(c(0.0099, 0.099, 0.99, 9.9, 99, 990, 9900, 99000, 990000, 9900000, 9.9e+07, 9.9e+08, 9.9e+09, 9.9e+10));is.finite(argv[[1]]); [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE -##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite16#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite16# #argv <- list(structure(numeric(0), .Dim = c(0L, 0L)));is.finite(argv[[1]]); <0 x 0 matrix> @@ -25024,7 +28006,7 @@ logical(0) #argv <- list(structure(1, .Tsp = c(1, 1, 1), class = 'ts'));is.finite(argv[[1]]); [1] TRUE -##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite19#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite19# #argv <- list(structure(c(100, -1e-13, Inf, -Inf, NaN, 3.14159265358979, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', ' NA')));is.finite(argv[[1]]); 100 -1e-13 Inf -Inf NaN 3.14 NA TRUE TRUE FALSE FALSE FALSE TRUE FALSE @@ -25041,7 +28023,7 @@ logical(0) [85] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [97] TRUE TRUE TRUE TRUE TRUE -##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite20#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite20# #argv <- list(structure(c(100L, 0L, NA, NA, NA, 3L, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', ' NA')));is.finite(argv[[1]]); 100 -1e-13 Inf -Inf NaN 3.14 NA TRUE TRUE FALSE FALSE FALSE TRUE FALSE @@ -25051,7 +28033,7 @@ logical(0) [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE [16] TRUE TRUE TRUE TRUE TRUE -##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite22#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite22# #argv <- list(structure(1:7, .Dim = c(1L, 7L)));is.finite(argv[[1]]); [,1] [,2] [,3] [,4] [,5] [,6] [,7] [1,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE @@ -25075,7 +28057,7 @@ logical(0) #argv <- list(structure(c(13991, 13995), class = 'Date'));is.finite(argv[[1]]); [1] TRUE TRUE -##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite3#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite3# #argv <- list(structure(485.051413351662, .Names = 'value'));is.finite(argv[[1]]); value TRUE @@ -25249,17 +28231,17 @@ fe #argv <- list(structure(3.14159265358979, class = structure('3.14159265358979', class = 'testit')));is.function(argv[[1]]); [1] FALSE -##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite1#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite1# #argv <- list(structure(c(100L, 0L, NA, NA, NA, 3L, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', ' NA')));is.infinite(argv[[1]]); 100 -1e-13 Inf -Inf NaN 3.14 NA FALSE FALSE FALSE FALSE FALSE FALSE FALSE -##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite10#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite10# #argv <- list(structure(c(100, -1e-13, Inf, -Inf, NaN, 3.14159265358979, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', ' NA')));is.infinite(argv[[1]]); 100 -1e-13 Inf -Inf NaN 3.14 NA FALSE FALSE TRUE TRUE FALSE FALSE FALSE -##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite11#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite11# #argv <- list(structure(c(0.140840156507829, 0.04056135019562, 0.0029302031336855, 0.244192917875952, 0.613916838192149, 0.0888451715064135, 0.0786481028238466, 0.000549230092684491, 0.00048785961836479, 0.235214398525727, 0.000402612842061681, 0.00423992719924668, 0.0355604120039037, 0.00432748168352161, 0.170388213068447, 0.466682597016338), .Names = c('1947', '1948', '1949', '1950', '1951', '1952', '1953', '1954', '1955', '1956', '1957', '1958', '1959', '1960', '1961', '1962')));is.infinite(argv[[1]]); 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE @@ -25270,7 +28252,7 @@ FALSE FALSE FALSE #argv <- list(4);is.infinite(argv[[1]]); [1] FALSE -##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite13#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite13# #argv <- list(structure(1:24, .Dim = 2:4));is.infinite(argv[[1]]); , , 1 @@ -25325,11 +28307,11 @@ B FALSE FALSE #argv <- list(c(Inf, -Inf));is.infinite(argv[[1]]); [1] TRUE TRUE -##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite3#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite3# #argv <- list(structure(logical(0), .Dim = c(0L, 0L)));is.infinite(argv[[1]]); <0 x 0 matrix> -##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite4#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite4# #argv <- list(structure(c(0.00241725013897913, 2.73568372449633e-07, 0.00400531454105884, 0.0305181933571734, 0.022064930648429, 0.000416097494498381, 0.0186357510997526, 0.00896237344987589, 0.00202331168264955, 0.00279067096737535, 0.0447487811957221, 0.000577210896095096, 0.00782925975125774, 0.033211430744327, 0.0093483442273581, 0.00136284952207105, 0.0275004422708864, 0.0135979349769553, 0.000181644594904405, 0.00803803085466393, 0.00350275333198457, 0.014998898960339, 5.39459255498146e-05, 0.00123860219686858, 1.13323906102913e-05, 0.0297916373848854, 0.0312890114433758, 5.85350754663798e-05, 0.0131002435454964, 0.00277072267615578, 0.0222123285012571, 0.00194205331979335, 0.0103231522531299, 0.0261098279661105, 0.0358853728812373, 1.13323906102913e-05, 0.0486308859679786, 0.000674881587747117, 0.0218633172580077, 0.000558592420498928, 0.000802158707806158, 0.0581913205761545, 0.000436809276845313, 0.00631994234432259, 0.000141965876420771, 0.000262833357340149, 0.0055965687842748, 0.000654737007593888, 0.0140931986366498, 0.00241538552182261, 0.00414822230660342, 0.00884150659070285, 0.0647626092888162, 0.0935599413167129, 0.00117891119201738, 0.00742609802768654, 0.0306399064130622, 0.0274290617824389, 0.00217883778937331, 0.0108387379377857, 0.0242348837396833, 0.0168720396936779, 0.022211269097018, 0.0355286679037712, 0.00017126708391638, 0.00443642409999561, 0.0068913158904869, 0.0635882367317516, 0.0566932963429416, 0.00904861729235097, 0.00038919481466495), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71')));is.infinite(argv[[1]]); 1 2 3 4 5 6 7 8 9 10 11 12 13 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE @@ -25369,7 +28351,7 @@ FALSE FALSE FALSE FALSE FALSE FALSE [20,] FALSE FALSE FALSE FALSE [21,] FALSE FALSE FALSE FALSE -##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite6#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite6# #argv <- list(structure(c(1.12411954394441, -0.567321126080105, 1.28594901629635, -0.519809468914999, -1.485548782458, -0.435305441405687, -0.281625943801696, -0.527525498975648, 2.60041695299567, NA), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10')));is.infinite(argv[[1]]); 1 2 3 4 5 6 7 8 9 10 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE @@ -25378,7 +28360,7 @@ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE #argv <- list(NULL);is.infinite(argv[[1]]); logical(0) -##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite8#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite8# #argv <- list(structure(c(0.00544194018731062, 0.00542949133552226, 1.20718999105839e-05, 0.00505497198006266, 0.827687885653788, 0.00315385274195005, 0.0023164952286401, 0.00117183915211372, 2.09167441982205, 0.00193959227691399, 0.00358084102808485, 3.39138861812986e-05, 0.00163051710052444, 0.00168735925488057, 0.0167253073891896, 0.237074502262169, 0.0118967636015583, 0.00307437031103621, 0.00114371252369823, 0.000860763872820255, 0.00028432076263802, 0.00329557354736053, 0.000123683950933913, 0.00026114238659798, 0.00471892942651347, 0.00317288091968884, 6.76955217513137e-05, 0.0119061189538054, 0.00233356124758579, 0.00672098496026968, 0.134965372025281, 0.00102115420103838, 0.00114816901125044), .Names = c('Craig Dunain', 'Ben Rha', 'Ben Lomond', 'Goatfell', 'Bens of Jura', 'Cairnpapple', 'Scolty', 'Traprain', 'Lairig Ghru', 'Dollar', 'Lomonds', 'Cairn Table', 'Eildon Two', 'Cairngorm', 'Seven Hills', 'Knock Hill', 'Black Hill', 'Creag Beag', 'Kildcon Hill', 'Meall Ant-Suidhe', 'Half Ben Nevis', 'Cow Hill', 'N Berwick Law', 'Creag Dubh', 'Burnswark', 'Largo Law', 'Criffel', 'Acmony', 'Ben Nevis', 'Knockfarrel', 'Two Breweries', 'Cockleroi', 'Moffat Chase')));is.infinite(argv[[1]]); Craig Dunain Ben Rha Ben Lomond Goatfell FALSE FALSE FALSE FALSE @@ -25399,7 +28381,7 @@ logical(0) Moffat Chase FALSE -##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite9#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite9# #argv <- list(structure(c(0.648648743252693, 0.52170345712821, -0.338075767187078, 0.169770656775468, -1.86324282017776, 0.362268009067608, 0.136032794890515, 0.901814933704047, -0.671639624694386, 1.79387977353953, 0.714576709724596, -0.471811539980989, -0.857026690426369, 0.226899513968796, 0.568565310101759, -0.944564385994918, 0.693403222263985, 0.02231307737364, -0.276817414323803, -0.344452836733253, -0.844829717537689, -0.421779195680793, -0.154748062715674, 1.43960300137753, 0.256965508768852, -0.295370227475694, 0.507911869619344, -0.346156318366332, -0.187948961031579, -0.454073164294974, -0.0895014237058297, 1.91227371168715, 0.779246572061347, 0.606406152381391, -0.0628430973426908, 2.1063179091687, -1.32672093069913, -0.754254955100625, -0.59565543740158, -1.95946772292555, -0.495798772099865, -3.58086046245482, -0.721772682345538, -0.254468243441054, 2.41750264738881, -0.0647957309150968, 1.87354174039771, -0.552199273430865, 0.732944502427441, 0.703597322009966, 0.875011400025303, -0.916329805907907, -0.297942295133666, -0.239141969395332, -1.79620422664673, -1.34633804643361, -Inf, 1.84762640960041, -0.344523591926435, 1.12935189480329, -0.902874350916712, -0.187948961031579, 0.444184743731147, -0.595767030989317, -0.878351658910786, 0.131398128073247, -1.16349118303155, -0.612790192876235, -0.231519954928205, -0.944564385994918, 0.136032794890519, -0.250233723215235, -0.972829009134415, 0.576852333601859, 0.226899513968797, -0.316245505808486, 0.101419270213227, 2.16953626752671, -0.383691077846572, 0.547999893193889, 0.00183871707028874, -1.28758691932778, 0.0676445397107313, -0.809987759639438, -1.04896153736838, 0.156556073105978, 0.248659709506608, 1.27246860456928, 0.554771572109539, 1.2326801378144, 2.2926344791142, 1.00034303387372, -0.554771572109538), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93')));is.infinite(argv[[1]]); 1 2 3 4 5 6 7 8 9 10 11 12 13 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE @@ -25925,7 +28907,7 @@ FALSE FALSE Warning message: In is.na(is.na) : is.na() applied to non-(list or vector) of type 'builtin' -##com.oracle.truffle.r.test.builtins.TestBuiltin_isna.testIsNA#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isna.testIsNA# #is.na(quote(x())) [1] FALSE Warning message: @@ -26149,7 +29131,7 @@ FALSE 419 TRUE 420 FALSE -##com.oracle.truffle.r.test.builtins.TestBuiltin_isna.testisna29#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isna.testisna29# #argv <- list(NULL);is.na(argv[[1]]); logical(0) Warning message: @@ -26314,7 +29296,7 @@ Levels: a b #argv <- list(NA);is.nan(argv[[1]]); [1] FALSE -##com.oracle.truffle.r.test.builtins.TestBuiltin_isnan.testisnan10#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isnan.testisnan10# #argv <- list(structure(c(1, 1, 1, 1, 1, 1), .Dim = 1:3));is.nan(argv[[1]]); , , 1 @@ -26332,7 +29314,7 @@ Levels: a b [1,] FALSE FALSE -##com.oracle.truffle.r.test.builtins.TestBuiltin_isnan.testisnan2#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isnan.testisnan2# #argv <- list(structure(1:7, .Names = c('a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7')));is.nan(argv[[1]]); a1 a2 a3 a4 a5 a6 a7 FALSE FALSE FALSE FALSE FALSE FALSE FALSE @@ -26341,7 +29323,7 @@ FALSE FALSE FALSE FALSE FALSE FALSE FALSE #argv <- list(1:3);is.nan(argv[[1]]); [1] FALSE FALSE FALSE -##com.oracle.truffle.r.test.builtins.TestBuiltin_isnan.testisnan4#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isnan.testisnan4# #argv <- list(structure(NaN, .Dim = c(1L, 1L)));is.nan(argv[[1]]); [,1] [1,] TRUE @@ -26354,7 +29336,7 @@ FALSE FALSE FALSE FALSE FALSE FALSE FALSE #argv <- list(NULL);is.nan(argv[[1]]); logical(0) -##com.oracle.truffle.r.test.builtins.TestBuiltin_isnan.testisnan7#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isnan.testisnan7# #argv <- list(structure(1:3, .Dim = c(3L, 1L)));is.nan(argv[[1]]); [,1] [1,] FALSE @@ -26799,6 +29781,10 @@ logical(0) #{ is.unsorted(c(1+1i,2+1i,2+1i), strictly=TRUE) } [1] TRUE +##com.oracle.truffle.r.test.builtins.TestBuiltin_isunsorted.testIsUnsorted#Output.IgnoreErrorContext# +#{ is.unsorted(c(1,2,2), strictly=NA) } +Error in is.unsorted(x, strictly) : invalid 'strictly' argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_isunsorted.testIsUnsorted# #{ is.unsorted(c(1,2,2,3), strictly=TRUE) } [1] TRUE @@ -26910,11 +29896,11 @@ logical(0) ##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector# #{ x<-list(1,3); } -##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector#Output.IgnoreErrorContext# #{is.vector(c(1,2), TRUE);} Error in is.vector(x, mode) : invalid 'mode' argument -##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector# +##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector#Output.IgnoreErrorContext# #{is.vector(c(1,2), c("sss", "dddd"));} Error in is.vector(x, mode) : invalid 'mode' argument @@ -27077,6 +30063,112 @@ attr(,"origin") [1] "(Intercept)" "gravity" "ph" "osmo" "conduct" [6] "urea" "log(calc)" +##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply# +#f <- function(...) { .Internal(lapply(1:4, NA)) }; f() +Error in f() : attempt to apply non-function + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply# +#f <- function(...) { .Internal(lapply(1:4, NULL)) }; f() +Error in f() : attempt to apply non-function + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply# +#f <- function(...) { .Internal(lapply(FUN=function(x){x})) }; f() +Error in f() : 1 argument passed to .Internal(lapply) which requires 2 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply# +#f <- function(...) { .Internal(lapply(NA, FUN=function(x){x})) }; f() +[[1]] +[1] NA + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply# +#f <- function(...) { .Internal(lapply(NULL, function(x){x})) }; f() +list() + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply# +#f <- function(...) { .Internal(lapply(X=1:4)) }; f() +Error in f() : 1 argument passed to .Internal(lapply) which requires 2 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#Ignored.ImplementationError# +#f <- function(...) { .Internal(lapply(X=c(function() {print('test1')}, function() {print('test2')}), FUN=function(x){x})) }; f() +[[1]] +function () +{ + print("test1") +} +<environment: 0x7fb02e3849c0> + +[[2]] +function () +{ + print("test2") +} +<environment: 0x7fb02e3849c0> + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#Output.IgnoreErrorContext# +#f <- function(...) { .Internal(lapply(X=environment(), FUN=function(x){x})) }; f() +Error in environment()[[i]] : + wrong arguments for subsetting an environment + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#Output.IgnoreErrorContext# +#f <- function(...) { .Internal(lapply(X=function() {print('test')}, FUN=function(x){x})) }; f() +Error in function() { : object of type 'closure' is not subsettable + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply# +#lapply(1:4, NA) +Error in match.fun(FUN) : 'NA' is not a function, character or symbol + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply# +#lapply(1:4, NULL) +Error in match.fun(FUN) : 'NULL' is not a function, character or symbol + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply# +#lapply(FUN=function(x){x}) +Error in lapply(FUN = function(x) { : + argument "X" is missing, with no default + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply# +#lapply(NA, FUN=function(x){x}) +[[1]] +[1] NA + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply# +#lapply(NULL, function(x){x}) +list() + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#Output.IgnoreErrorContext# +#lapply(X=1:4) +Error in match.fun(FUN) : argument "FUN" is missing, with no default + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#Output.IgnoreWhitespace# +#lapply(X=c(function() {print("test1")}, function() {print("test2")}), FUN=function(x){x}) +[[1]] +function () +{ + print("test1") +} + +[[2]] +function () +{ + print("test2") +} + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply# +#lapply(X=environment(), FUN=function(x){x}) +list() + +##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply# +#lapply(X=function() {print('test')}, FUN=function(x){x}) +[[1]] +{ + print("test") +} + + ##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply# #{ .Internal(lapply(1:4, 42)) } Error: attempt to apply non-function @@ -27835,7 +30927,7 @@ Error in lengths(quote(a)) : 'x' must be a list or atomic vector #{ x <- 1 ; levels(x)<-4.5; levels(x);} [1] 4.5 -##com.oracle.truffle.r.test.builtins.TestBuiltin_levels.testLevels#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_levels.testLevels#Output.MayIgnoreErrorContext# #{ x <- 1 ; levels(x)<-NULL; levels(notx)} Error in levels(notx) : object 'notx' not found @@ -28310,7 +31402,7 @@ numeric(0) 41 42 7.352977 9.355336 -##com.oracle.truffle.r.test.builtins.TestBuiltin_lgamma.testlgamma9#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_lgamma.testlgamma9# #argv <- list(Inf);do.call('lgamma', argv) [1] Inf Warning message: @@ -29517,7 +32609,7 @@ attr(,"class") [5,] -0.4969603 -0.31475219 0.45819205 -0.65231472 0.1360408 -##com.oracle.truffle.r.test.builtins.TestBuiltin_list.testlist55#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_list.testlist55# #argv <- list(object = c(0, 0, 0, 0, 0, 1.75368801162502e-134, 0, 0, 0, 2.60477585273833e-251, 1.16485035372295e-260, 0, 1.53160350210786e-322, 0.333331382328728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.44161262707711e-123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.968811545398e-173, 0, 8.2359965384697e-150, 0, 0, 0, 0, 6.51733217171341e-10, 0, 2.36840184577368e-67, 0, 9.4348408357524e-307, 0, 1.59959906013771e-89, 0, 8.73836857865034e-286, 7.09716190970992e-54, 0, 0, 0, 1.530425353017e-274, 8.57590058044551e-14, 0.333333106397154, 0, 0, 1.36895217898448e-199, 2.0226102635783e-177, 5.50445388209462e-42, 0, 0, 0, 0, 1.07846402051283e-44, 1.88605464411243e-186, 1.09156111051203e-26, 0, 3.0702877273237e-124, 0.333333209689785, 0, 0, 0, 0, 0, 0, 3.09816093866831e-94, 0, 0, 4.7522727332095e-272, 0, 0, 2.30093251441394e-06, 0, 0, 1.27082826644707e-274, 0, 0, 0, 0, 0, 0, 0, 4.5662025456054e-65, 0, 2.77995853978268e-149, 0, 0, 0));list(argv[[1]]); [[1]] [1] 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 @@ -29965,7 +33057,7 @@ Error in eval(expr, envir, enclos) : object 'weight' not found #require(stats);lm(formula = weight ~ group, method = 'model.frame') Error in eval(expr, envir, enclos) : object 'weight' not found -##com.oracle.truffle.r.test.builtins.TestBuiltin_lm.testlm334#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_lm.testlm334# #require(stats);lm(data = LifeCycleSavings, formula = sr ~ pop15 + pop75 + dpi + ddpi) Call: @@ -29976,7 +33068,7 @@ Coefficients: 28.5660865 -0.4611931 -1.6914977 -0.0003369 0.4096949 -##com.oracle.truffle.r.test.builtins.TestBuiltin_lm.testlm445#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_lm.testlm445# #require(stats);lm(data = attitude, formula = rating ~ .) Call: @@ -29989,7 +33081,7 @@ Coefficients: -0.21706 -##com.oracle.truffle.r.test.builtins.TestBuiltin_lm.testlm875#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_lm.testlm875# #require(stats); lm(data = mtcars, formula = 100/mpg ~ disp + hp + wt + am) Call: @@ -30000,7 +33092,7 @@ Coefficients: 0.740648 0.002703 0.005275 1.001303 0.155815 -##com.oracle.truffle.r.test.builtins.TestBuiltin_lm.testlm876#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_lm.testlm876# #require(stats); lm(data = npk, formula = yield ~ block + N * P * K, singular.ok = TRUE) Call: @@ -30059,7 +33151,7 @@ Coefficients: #require(stats); lm(formula = y ~ x) Error in eval(expr, envir, enclos) : object 'y' not found -##com.oracle.truffle.r.test.builtins.TestBuiltin_lockEnvironment.testlockEnvironment#Ignored.MissingBuiltin# +##com.oracle.truffle.r.test.builtins.TestBuiltin_lockEnvironment.testlockEnvironment# #e <- new.env(); e$a <- 'foo'; lockEnvironment(e, 'a'); e$a <- 123 Error in e$a <- 123 : cannot change value of locked binding for 'a' @@ -30118,6 +33210,460 @@ Error in lockEnvironment("foo", TRUE) : not an environment #{ round( log(10,2), digits = 5 ) } [1] 3.32193 +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(-10-1i, 10) } +[1] 1.002161-1.321091i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(0+0i) } +[1] -Inf+0i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(0+0i, 0) } +[1] NaN+NaNi +Warning message: +In log(0 + (0+0i), 0) : NaNs produced in function "log" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(0+0i, 0+0i) } +[1] NaN+NaNi +Warning message: +In log(0 + (0+0i), 0 + (0+0i)) : NaNs produced in function "log" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#Ignored.ImplementationError# +#{ log(0+0i, 1) } +[1] -Inf+NaNi +Warning message: +In log(0 + (0+0i), 1) : NaNs produced in function "log" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(0.0, 0+0i) } +[1] NaN+NaNi +Warning message: +In log(0, 0 + (0+0i)) : NaNs produced in function "log" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(0L, 0+0i) } +[1] NaN+NaNi +Warning message: +In log(0L, 0 + (0+0i)) : NaNs produced in function "log" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(1+1i) } +[1] 0.3465736+0.7853982i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(1+1i, -1-1i) } +[1] -0.3050968+0.1919672i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(1+1i, 0) } +[1] 0+0i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#Ignored.ImplementationError# +#{ log(1+1i, 1) } +[1] Inf+Infi + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(1+1i, 1+1i) } +[1] 1+0i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(1+1i, 1-1i) } +[1] -0.674032+0.7387021i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(1+1i, 10+10i) } +[1] 0.2010479+0.236866i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(1+1i, NA_complex_) } +[1] NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(1, 1+1i) } +[1] 0+0i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(1.0, 1+1i) } +[1] 0+0i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(10+10i, 10) } +[1] 1.150515+0.341094i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(10+10i, 10+10i) } +[1] 1+0i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(10+1i, -10) } +[1] 0.3708579-0.4627043i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(10+1i, 10) } +[1] 1.002161+0.043286i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(10, 10+10i) } +[1] 0.7989521-0.236866i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(10-1i, 10) } +[1] 1.002161-0.043286i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(10.0, 1+1i) } +[1] 1.082842-2.453915i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(F, 0+0i) } +[1] NaN+NaNi +Warning message: +In log(F, 0 + (0+0i)) : NaNs produced in function "log" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(NA_complex_) } +[1] NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(T, 1+1i) } +[1] 0+0i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(1+1i)) } +[1] 0.3465736+0.7853982i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(1+1i), 0) } +[1] 0+0i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(1+1i, 2+1i)) } +[1] 0.3465736+0.7853982i 0.8047190+0.4636476i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(1+1i, 2+2i), NA) } +[1] NA NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(1+1i, 2+2i), NaN) } +[1] NaN+NaNi NaN+NaNi + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(1+1i, 2+2i), complex(real=1, imaginary=NA)) } +[1] NA NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(1+1i, 2+2i), complex(real=1, imaginary=NaN)) } +[1] NaN+NaNi NaN+NaNi + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(1+1i, 2+2i), complex(real=NA, imaginary=1)) } +[1] NA NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(1+1i, 2+2i), complex(real=NaN, imaginary=1)) } +[1] NaN+NaNi NaN+NaNi + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(1+1i, 2+2i), complex(real=NaN, imaginary=NaN)) } +[1] NaN+NaNi NaN+NaNi + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(1+1i, 2+2i, complex(real=NA, imaginary=NA))) } +[1] 0.3465736+0.7853982i 1.0397208+0.7853982i NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(1+1i, NA_complex_)) } +[1] 0.3465736+0.7853982i NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(10+10i, 10), 10) } +[1] 1.150515+0.341094i 1.000000+0.000000i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(10+10i, 10+10i), 10+10i) } +[1] 1+0i 1+0i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(10+1i, 10), 10) } +[1] 1.002161+0.043286i 1.000000+0.000000i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(10, 10), 10+10i) } +[1] 0.7989521-0.236866i 0.7989521-0.236866i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(10, 10+10i), 10) } +[1] 1.000000+0.000000i 1.150515+0.341094i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(10.0, 10+10i), 10) } +[1] 1.000000+0.000000i 1.150515+0.341094i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(10.0, 10.0), 10+10i) } +[1] 0.7989521-0.236866i 0.7989521-0.236866i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(T, 10+10i), 10) } +[1] 0.000000+0.000000i 1.150515+0.341094i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(c(T, F), 1+1i) } +[1] 0+ 0i -Inf+Infi + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(complex(real=1, imaginary=NA)) } +[1] NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(complex(real=NA, imaginary=1i)) } +[1] NA +Warning message: +In complex(real = NA, imaginary = 0+1i) : + imaginary parts discarded in coercion + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex# +#{ log(complex(real=NA, imaginary=NA)) } +[1] NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#Ignored.ImplementationError# +#{ log(complex(real=sqrt(.5), imaginary=sqrt(.5)), 1) } +[1] Inf+Infi + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble# +#{ log(-1.1) } +[1] NaN +Warning message: +In log(-1.1) : NaNs produced + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble# +#{ log(0.0) } +[1] -Inf + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble# +#{ log(1.0, 1.0) } +[1] NaN +Warning message: +NaNs produced + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble# +#{ log(1.1) } +[1] 0.09531018 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble# +#{ log(10, NA_real_) } +[1] NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble# +#{ log(10.0, -1.0) } +[1] NaN +Warning message: +NaNs produced + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble# +#{ log(10.0, 1.0) } +[1] Inf + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble# +#{ log(10.0, 10.0) } +[1] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble# +#{ log(NA_real_) } +[1] NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble# +#{ log(c(1.0, 0.0, 10.0), 1.0) } +[1] NaN -Inf Inf +Warning message: +NaNs produced + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble# +#{ log(c(1.0, 0.0, 10.0), 10.0) } +[1] 0 -Inf 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble# +#{ log(c(1.0, 2.0), NA) } +[1] NA NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble# +#{ log(c(1.0, 2.0), NaN) } +[1] NaN NaN + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble# +#{ log(c(1.0, 2.0, NA)) } +[1] 0.0000000 0.6931472 NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble# +#{ log(c(10, NA_real_)) } +[1] 2.302585 NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt# +#{ log(-1L) } +[1] NaN +Warning message: +In log(-1L) : NaNs produced + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt# +#{ log(0L) } +[1] -Inf + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt# +#{ log(0L, NA_integer_) } +[1] NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt# +#{ log(10L, -1L) } +[1] NaN +Warning message: +NaNs produced + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt# +#{ log(10L, 10L) } +[1] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt# +#{ log(10L, 1L) } +[1] Inf + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt# +#{ log(1L) } +[1] 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt# +#{ log(1L, 1L) } +[1] NaN +Warning message: +NaNs produced + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt# +#{ log(NA_integer_) } +[1] NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt# +#{ log(c(0L, NA_integer_)) } +[1] -Inf NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt# +#{ log(c(1L, 0L, 10L), 1L) } +[1] NaN -Inf Inf +Warning message: +NaNs produced + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt# +#{ log(c(1L, 1L, 0L, 10L), 10L) } +[1] 0 0 -Inf 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt# +#{ log(c(1L, 2L), NA) } +[1] NA NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt# +#{ log(c(1L, 2L), NaN) } +[1] NaN NaN + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt# +#{ log(c(1L, 2L, NA)) } +[1] 0.0000000 0.6931472 NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical# +#{ log(F, F) } +[1] NaN +Warning message: +NaNs produced + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical# +#{ log(F, T) } +[1] -Inf + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical# +#{ log(T) } +[1] 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical# +#{ log(T, F) } +[1] 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical# +#{ log(T, T) } +[1] NaN +Warning message: +NaNs produced + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical# +#{ log(c(T)) } +[1] 0 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical# +#{ log(c(T, F)) } +[1] 0 -Inf + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical# +#{ log(c(T, F), T) } +[1] NaN -Inf +Warning message: +NaNs produced + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical# +#{ log(c(T, T), NA) } +[1] NA NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical# +#{ log(c(T, T), NaN) } +[1] NaN NaN + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testProducedManyNaNsButOneWarnig# +#{ log(c(0+0i, 0+0i), 0) } +[1] NaN+NaNi NaN+NaNi +Warning message: +In log(c(0 + (0+0i), 0 + (0+0i)), 0) : NaNs produced in function "log" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testProducedManyNaNsButOneWarnig# +#{ log(c(0+0i, 0+0i), 0+0i) } +[1] NaN+NaNi NaN+NaNi +Warning message: +In log(c(0 + (0+0i), 0 + (0+0i)), 0 + (0+0i)) : + NaNs produced in function "log" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testProducedManyNaNsButOneWarnig# +#{ log(c(0.0, 0.0), 0+0i) } +[1] NaN+NaNi NaN+NaNi +Warning message: +In log(c(0, 0), 0 + (0+0i)) : NaNs produced in function "log" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testProducedManyNaNsButOneWarnig# +#{ log(c(0L, 0L), 0+0i) } +[1] NaN+NaNi NaN+NaNi +Warning message: +In log(c(0L, 0L), 0 + (0+0i)) : NaNs produced in function "log" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testProducedManyNaNsButOneWarnig# +#{ log(c(1.0, 1.0), 1.0) } +[1] NaN NaN +Warning message: +NaNs produced + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testProducedManyNaNsButOneWarnig# +#{ log(c(1L, 1L), 1L) } +[1] NaN NaN +Warning message: +NaNs produced + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testProducedManyNaNsButOneWarnig# +#{ log(c(F, F), 0+0i) } +[1] NaN+NaNi NaN+NaNi +Warning message: +In log(c(F, F), 0 + (0+0i)) : NaNs produced in function "log" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testProducedManyNaNsButOneWarnig# +#{ log(c(F, F), F) } +[1] NaN NaN +Warning message: +NaNs produced + ##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testlog1# #argv <- list(0.7800058115849);do.call('log', argv) [1] -0.2484539 @@ -31865,6 +35411,10 @@ object "foo" #argv <- list(0L, 0L, 0L, FALSE, NULL, FALSE, FALSE); .Internal(matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]])) <0 x 0 matrix> +##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum# +#max(c(1,NA,2), na.rm=NA) +[1] 2 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum# #max(v<-42) [1] 42 @@ -32002,7 +35552,7 @@ In max(NULL) : no non-missing arguments to max; returning -Inf #{ max(as.character(NA), as.character(NA), na.rm=FALSE) } [1] NA -##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum# #{ max(as.character(NA), as.character(NA), na.rm=TRUE) } [1] NA Warning message: @@ -32013,7 +35563,7 @@ In max(as.character(NA), as.character(NA), na.rm = TRUE) : #{ max(as.character(NA), na.rm=FALSE) } [1] NA -##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum# #{ max(as.character(NA), na.rm=TRUE) } [1] NA Warning message: @@ -32024,7 +35574,7 @@ In max(as.character(NA), na.rm = TRUE) : #{ max(as.double(NA), as.double(NA), na.rm=FALSE) } [1] NA -##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum# #{ max(as.double(NA), as.double(NA), na.rm=TRUE) } [1] -Inf Warning message: @@ -32035,7 +35585,7 @@ In max(as.double(NA), as.double(NA), na.rm = TRUE) : #{ max(as.double(NA), na.rm=FALSE) } [1] NA -##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum# #{ max(as.double(NA), na.rm=TRUE) } [1] -Inf Warning message: @@ -32334,7 +35884,7 @@ Time difference of 31 days #argv <- structure(list(x = c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 50), trim = 0.5), .Names = c('x', 'trim'));do.call('mean', argv) [1] 5.5 -##com.oracle.truffle.r.test.builtins.TestBuiltin_mean.testmean22#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_mean.testmean22# #argv <- structure(list(x = structure(c(2L, 1L, 2L, 2L), .Label = c('FALSE', 'TRUE'), class = 'factor')), .Names = 'x');do.call('mean', argv) [1] NA Warning message: @@ -32507,6 +36057,11 @@ $b [1] 2 +##com.oracle.truffle.r.test.builtins.TestBuiltin_mget.testMGet# +#{ a<- 1; b <- 2; mget(c('a', 'b'), envir=1) } +Error in mget(c("a", "b"), envir = 1) : + second argument must be an environment + ##com.oracle.truffle.r.test.builtins.TestBuiltin_mget.testMGet# #{ a<- 1; mget(c("a", "b"), ifnotfound=list(100)) } $a @@ -32568,6 +36123,10 @@ list sys.call(1) +##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum# +#min(c(1,NA,2), na.rm=NA) +[1] 1 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum# #{ is.logical(min(TRUE)) } [1] FALSE @@ -32689,7 +36248,7 @@ In min(NULL) : no non-missing arguments to min; returning Inf #{ min(as.character(NA), as.character(NA), na.rm=FALSE) } [1] NA -##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum# #{ min(as.character(NA), as.character(NA), na.rm=TRUE) } [1] NA Warning message: @@ -32700,7 +36259,7 @@ In min(as.character(NA), as.character(NA), na.rm = TRUE) : #{ min(as.character(NA), na.rm=FALSE) } [1] NA -##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum# #{ min(as.character(NA), na.rm=TRUE) } [1] NA Warning message: @@ -32711,7 +36270,7 @@ In min(as.character(NA), na.rm = TRUE) : #{ min(as.double(NA), as.double(NA), na.rm=FALSE) } [1] NA -##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum# #{ min(as.double(NA), as.double(NA), na.rm=TRUE) } [1] Inf Warning message: @@ -32722,7 +36281,7 @@ In min(as.double(NA), as.double(NA), na.rm = TRUE) : #{ min(as.double(NA), na.rm=FALSE) } [1] NA -##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum# #{ min(as.double(NA), na.rm=TRUE) } [1] Inf Warning message: @@ -32940,6 +36499,10 @@ Levels: A < B < C #{ f <- function(a) { g(a) } ; g <- function(b=2) { missing(b) } ; f() } [1] TRUE +##com.oracle.truffle.r.test.builtins.TestBuiltin_missing.testMissing# +#{ f <- function(a) { missing("a") }; f(); f(1) } +[1] FALSE + ##com.oracle.truffle.r.test.builtins.TestBuiltin_missing.testMissing# #{ f <- function(a,b,c) { missing(b) } ; f(1,,2) } [1] TRUE @@ -33926,6 +37489,51 @@ a f g #{ nchar(c(10,130)) } [1] 2 3 +##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNCharKeepNA# +#nchar(c('aasd', NA), keepNA=NA) +[1] 4 NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNCharKeepNA# +#nchar(c('aasd', NA, 'asdasd'), keepNA=TRUE) +[1] 4 NA 6 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNCharTypeMatching# +#nchar('aasd', type='') +Error in nchar("aasd", type = "") : invalid 'type' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNCharTypeMatching# +#nchar('aasd', type='cha') +[1] 4 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNCharTypeMatching# +#nchar('aasd', type='charsxzy') +Error in nchar("aasd", type = "charsxzy") : invalid 'type' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNULLAndMissing# +#nchar() +Error in nchar() : argument "x" is missing, with no default + +##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNULLAndMissing# +#nchar(type = 'chars', allowNA = FALSE, keepNA = NA) +Error in nchar(type = "chars", allowNA = FALSE, keepNA = NA) : + argument "x" is missing, with no default + +##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNULLAndMissing# +#nchar(wrongArg="a") +Error in nchar(wrongArg = "a") : unused argument (wrongArg = "a") + +##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNULLAndMissing# +#nchar(wrongArg='a') +Error in nchar(wrongArg = "a") : unused argument (wrongArg = "a") + +##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNULLAndMissing# +#nchar(x=NULL) +integer(0) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNULLAndMissing# +#nchar(x=NULL, type = 'chars', allowNA = FALSE, keepNA = NA) +integer(0) + ##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testnchar1# #argv <- list('DtTmCl> format(.leap.seconds) # all 24 leap seconds in your timezone', 'c', FALSE, FALSE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]])) [1] 76 @@ -33943,8 +37551,13 @@ a f g integer(0) ##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testnchar13# -#argv <- list(structure(c('rpart', 'recommended', '4.1-1', '2013-03-20', 'c(person(\'Terry\', \'Therneau\', role = \'aut\',\n\t email = \'therneau@mayo.edu\'),\n person(\'Beth\', \'Atkinson\', role = \'aut\',\t\n\t email = \'atkinson@mayo.edu\'),\n person(\'Brian\', \'Ripley\', role = c(\'aut\', \'trl\', \'cre\'),\n email = \'ripley@stats.ox.ac.uk\',\n\t\t comment = \'author of R port\'))', 'Recursive partitioning and regression trees', 'Recursive Partitioning', 'R (>= 2.14.0), graphics, stats, grDevices', 'survival', 'GPL-2 | GPL-3', 'yes', 'yes', 'Maintainers are not available to give advice on using a package\nthey did not author.', '2013-03-20 07:27:05 UTC; ripley', 'Terry Therneau [aut],\n Beth Atkinson [aut],\n Brian Ripley [aut, trl, cre] (author of R port)', 'Brian Ripley <ripley@stats.ox.ac.uk>'), .Names = c('Package', 'Priority', 'Version', 'Date', 'Authors@R', 'Description', 'Title', 'Depends', 'Suggests', 'License', 'LazyData', 'ByteCompile', 'Note', 'Packaged', 'Author', 'Maintainer')), 'c', TRUE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]])) -Error in argv[[4]] : subscript out of bounds +#argv <- list(structure(c('rpart', 'recommended', '4.1-1', '2013-03-20', 'c(person(\'Terry\', \'Therneau\', role = \'aut\',\n\t email = \'therneau@mayo.edu\'),\n person(\'Beth\', \'Atkinson\', role = \'aut\',\t\n\t email = \'atkinson@mayo.edu\'),\n person(\'Brian\', \'Ripley\', role = c(\'aut\', \'trl\', \'cre\'),\n email = \'ripley@stats.ox.ac.uk\',\n\t\t comment = \'author of R port\'))', 'Recursive partitioning and regression trees', 'Recursive Partitioning', 'R (>= 2.14.0), graphics, stats, grDevices', 'survival', 'GPL-2 | GPL-3', 'yes', 'yes', 'Maintainers are not available to give advice on using a package\nthey did not author.', '2013-03-20 07:27:05 UTC; ripley', 'Terry Therneau [aut],\n Beth Atkinson [aut],\n Brian Ripley [aut, trl, cre] (author of R port)', 'Brian Ripley <ripley@stats.ox.ac.uk>'), .Names = c('Package', 'Priority', 'Version', 'Date', 'Authors@R', 'Description', 'Title', 'Depends', 'Suggests', 'License', 'LazyData', 'ByteCompile', 'Note', 'Packaged', 'Author', 'Maintainer')), 'c', TRUE, FALSE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]])) + Package Priority Version Date Authors@R Description + 5 11 5 10 345 43 + Title Depends Suggests License LazyData ByteCompile + 22 41 8 13 3 3 + Note Packaged Author Maintainer + 84 31 94 36 ##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testnchar2# #argv <- list(c('\'a\'', '\'b\'', NA, NA, NA, '\'f\'', '\'g\'', '\'h\'', '\'i\'', '\'j\'', '\'k\'', '\'l\''), 'w', FALSE, FALSE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]])) @@ -33999,7 +37612,7 @@ Error in argv[[4]] : subscript out of bounds #parent.env(new.env()) <environment: R_GlobalEnv> -##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext# #{ ngettext(-1, "a", "b") } Error in ngettext(-1, "a", "b") : invalid 'n' argument @@ -34007,7 +37620,7 @@ Error in ngettext(-1, "a", "b") : invalid 'n' argument #{ ngettext(0, "a", "b") } [1] "b" -##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext# #{ ngettext(1+1i, "a", "b") } [1] "a" Warning message: @@ -34017,7 +37630,7 @@ In ngettext(1 + (0+1i), "a", "b") : imaginary parts discarded in coercion #{ ngettext(1, "a", "b") } [1] "a" -##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext# #{ ngettext(1, "a", NULL) } Error in ngettext(1, "a", NULL) : 'msg2' must be a character string @@ -34025,20 +37638,20 @@ Error in ngettext(1, "a", NULL) : 'msg2' must be a character string #{ ngettext(1, "a", c("b")) } [1] "a" -##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext# #{ ngettext(1, "a", c("b", "c")) } Error in ngettext(1, "a", c("b", "c")) : 'msg2' must be a character string -##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext# #{ ngettext(1, "a", c(1)) } Error in ngettext(1, "a", c(1)) : 'msg2' must be a character string -##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext# #{ ngettext(1, NULL, "b") } Error in ngettext(1, NULL, "b") : 'msg1' must be a character string -##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext# #{ ngettext(1, NULL, NULL) } Error in ngettext(1, NULL, NULL) : 'msg1' must be a character string @@ -34046,12 +37659,12 @@ Error in ngettext(1, NULL, NULL) : 'msg1' must be a character string #{ ngettext(1, c("a"), "b") } [1] "a" -##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext# #{ ngettext(1, c("a", "c"), "b") } Error in ngettext(1, c("a", "c"), "b") : 'msg1' must be a character string -##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext# #{ ngettext(1, c(1), "b") } Error in ngettext(1, c(1), "b") : 'msg1' must be a character string @@ -34093,6 +37706,10 @@ Warning messages: #argv <- structure(list(x = structure(c(0, 3313, 2963, 3175, 3339, 2762, 3276, 2610, 4485, 2977, 3030, 4532, 2753, 3949, 2865, 2282, 2179, 3000, 817, 3927, 1991, 3313, 0, 1318, 1326, 1294, 1498, 2218, 803, 1172, 2018, 1490, 1305, 645, 636, 521, 1014, 1365, 1033, 1460, 2868, 1802, 2963, 1318, 0, 204, 583, 206, 966, 677, 2256, 597, 172, 2084, 690, 1558, 1011, 925, 747, 285, 1511, 1616, 1175, 3175, 1326, 204, 0, 460, 409, 1136, 747, 2224, 714, 330, 2052, 739, 1550, 1059, 1077, 977, 280, 1662, 1786, 1381, 3339, 1294, 583, 460, 0, 785, 1545, 853, 2047, 1115, 731, 1827, 789, 1347, 1101, 1209, 1160, 340, 1794, 2196, 1588, 2762, 1498, 206, 409, 785, 0, 760, 1662, 2436, 460, 269, 2290, 714, 1764, 1035, 911, 583, 465, 1497, 1403, 937, 3276, 2218, 966, 1136, 1545, 760, 0, 1418, 3196, 460, 269, 2971, 1458, 2498, 1778, 1537, 1104, 1176, 2050, 650, 1455, 2610, 803, 677, 747, 853, 1662, 1418, 0, 1975, 1118, 895, 1936, 158, 1439, 425, 328, 591, 513, 995, 2068, 1019, 4485, 1172, 2256, 2224, 2047, 2436, 3196, 1975, 0, 2897, 2428, 676, 1817, 698, 1693, 2185, 2565, 1971, 2631, 3886, 2974, 2977, 2018, 597, 714, 1115, 460, 460, 1118, 2897, 0, 550, 2671, 1159, 2198, 1479, 1238, 805, 877, 1751, 949, 1155, 3030, 1490, 172, 330, 731, 269, 269, 895, 2428, 550, 0, 2280, 863, 1730, 1183, 1098, 851, 457, 1683, 1500, 1205, 4532, 1305, 2084, 2052, 1827, 2290, 2971, 1936, 676, 2671, 2280, 0, 1178, 668, 1762, 2250, 2507, 1799, 2700, 3231, 2937, 2753, 645, 690, 739, 789, 714, 1458, 158, 1817, 1159, 863, 1178, 0, 1281, 320, 328, 724, 471, 1048, 2108, 1157, 3949, 636, 1558, 1550, 1347, 1764, 2498, 1439, 698, 2198, 1730, 668, 1281, 0, 1157, 1724, 2010, 1273, 2097, 3188, 2409, 2865, 521, 1011, 1059, 1101, 1035, 1778, 425, 1693, 1479, 1183, 1762, 320, 1157, 0, 618, 1109, 792, 1011, 2428, 1363, 2282, 1014, 925, 1077, 1209, 911, 1537, 328, 2185, 1238, 1098, 2250, 328, 1724, 618, 0, 331, 856, 586, 2187, 898, 2179, 1365, 747, 977, 1160, 583, 1104, 591, 2565, 805, 851, 2507, 724, 2010, 1109, 331, 0, 821, 946, 1754, 428, 3000, 1033, 285, 280, 340, 465, 1176, 513, 1971, 877, 457, 1799, 471, 1273, 792, 856, 821, 0, 1476, 1827, 1249, 817, 1460, 1511, 1662, 1794, 1497, 2050, 995, 2631, 1751, 1683, 2700, 1048, 2097, 1011, 586, 946, 1476, 0, 2707, 1209, 3927, 2868, 1616, 1786, 2196, 1403, 650, 2068, 3886, 949, 1500, 3231, 2108, 3188, 2428, 2187, 1754, 1827, 2707, 0, 2105, 1991, 1802, 1175, 1381, 1588, 937, 1455, 1019, 2974, 1155, 1205, 2937, 1157, 2409, 1363, 898, 428, 1249, 1209, 2105, 0), .Dim = c(21L, 21L), .Dimnames = list(c('Athens', 'Barcelona', 'Brussels', 'Calais', 'Cherbourg', 'Cologne', 'Copenhagen', 'Geneva', 'Gibraltar', 'Hamburg', 'Hook of Holland', 'Lisbon', 'Lyons', 'Madrid', 'Marseilles', 'Milan', 'Munich', 'Paris', 'Rome', 'Stockholm', 'Vienna'), c('Athens', 'Barcelona', 'Brussels', 'Calais', 'Cherbourg', 'Cologne', 'Copenhagen', 'Geneva', 'Gibraltar', 'Hamburg', 'Hook of Holland', 'Lisbon', 'Lyons', 'Madrid', 'Marseilles', 'Milan', 'Munich', 'Paris', 'Rome', 'Stockholm', 'Vienna')))), .Names = 'x');do.call('NROW', argv) [1] 21 +##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.keepNATests# +#nzchar(c('aasd', NA), keepNA=NA) +[1] TRUE TRUE + ##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.keepNATests# #nzchar(c('asdasd', NA), keepNA=FALSE) [1] TRUE TRUE @@ -34101,10 +37718,32 @@ Warning messages: #nzchar(c('asdasd', NA), keepNA=TRUE) [1] TRUE NA +##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.nonStringArgs# +#nchar(wrongArgName="a") +Error in nchar(wrongArgName = "a") : unused argument (wrongArgName = "a") + +##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.nonStringArgs# +#nchar(wrongArgName='a') +Error in nchar(wrongArgName = "a") : unused argument (wrongArgName = "a") + +##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.nonStringArgs# +#nzchar(NA) +[1] TRUE + ##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.nonStringArgs# #nzchar(NULL) logical(0) +##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.nonStringArgs# +#nzchar(keepNA=F) +Error in nzchar(keepNA = F) : + supplied argument name 'keepNA' does not match 'x' + +##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.nonStringArgs# +#nzchar(keepNA=NA) +Error in nzchar(keepNA = NA) : + supplied argument name 'keepNA' does not match 'x' + ##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.nonStringArgs# #nzchar(list('x', 42, list('a'), list())) [1] TRUE TRUE TRUE TRUE @@ -34289,41 +37928,45 @@ NULL [1] 1 2 3 4 5 6 7 8 9 10 ##com.oracle.truffle.r.test.builtins.TestBuiltin_on_exit.testOnExit# -#n = function() { on.exit() }; n() +#f <- function() { on.exit() }; f() ##com.oracle.truffle.r.test.builtins.TestBuiltin_on_exit.testOnExit# -#n = function() { on.exit(print("test")); on.exit(); print("some") }; n() +#f <- function() { on.exit(print('test')); on.exit(); print('some') }; f() [1] "some" ##com.oracle.truffle.r.test.builtins.TestBuiltin_on_exit.testOnExit# -#n = function() { on.exit(print("test")); on.exit(print("test2")); print("some") }; n() +#f <- function() { on.exit(print('test')); on.exit(print('test2')); print('some') }; f() [1] "some" [1] "test2" ##com.oracle.truffle.r.test.builtins.TestBuiltin_on_exit.testOnExit# -#n = function() { on.exit(print("test")); on.exit(print("test2")); print("some"); on.exit() }; n() +#f <- function() { on.exit(print('test')); on.exit(print('test2')); print('some'); on.exit() }; f() [1] "some" ##com.oracle.truffle.r.test.builtins.TestBuiltin_on_exit.testOnExit# -#n = function() { on.exit(print("test")); on.exit(print("test2", TRUE)); print("some") }; n() +#f <- function() { on.exit(print('test')); on.exit(print('test2', TRUE)); print('some') }; f() [1] "some" [1] "test2" ##com.oracle.truffle.r.test.builtins.TestBuiltin_on_exit.testOnExit# -#n = function() { on.exit(print("test")); print("some") }; n() +#f <- function() { on.exit(print('test')); print('some') }; f() [1] "some" [1] "test" ##com.oracle.truffle.r.test.builtins.TestBuiltin_on_exit.testOnExit# -#n = function() { on.exit(print("test", TRUE)); on.exit(print("test2")); print("some") }; n() +#f <- function() { on.exit(print('test', TRUE)); on.exit(print('test2')); print('some') }; f() [1] "some" [1] "test2" ##com.oracle.truffle.r.test.builtins.TestBuiltin_on_exit.testOnExit# -#n = function() { on.exit(print("test", TRUE)); print("some") }; n() +#f <- function() { on.exit(print('test', TRUE)); print('some') }; f() [1] "some" [1] "test" +##com.oracle.truffle.r.test.builtins.TestBuiltin_on_exit.testOnExit# +#f <- function() { on.exit(return(5)); return(1) }; f() +[1] 5 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testBooleanOperators# #as.symbol('*') == '*' [1] TRUE @@ -36470,7 +40113,7 @@ y ~ a + b:c + d + e + e:d #argv <- list(structure(character(0), .Dim = c(0L, 7L), .Dimnames = list(NULL, c('description', 'class', 'mode', 'text', 'isopen', 'can read', 'can write'))));`(`(argv[[1]]); description class mode text isopen can read can write -##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators207#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators207# #argv <- list(structure(list(coefficients = structure(c(1.47191076131574, 0.586694550701453, NA, 0.258706725324317), .Names = c('(Intercept)', 'x1', 'x2', 'x3')), residuals = structure(c(0.224762433374997, 0.4813346401898, -0.548705796690786, -0.873306430909872, 0.3255545927283, -0.288240908441576, 0.530823516045489, -0.0649703574297026, 1.2699009772491, -1.05715266611575), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10')), effects = structure(c(-18.0083860263211, 7.91372047070235, 0.594462796282497, -0.733976126666906, 0.546582698364345, -0.032332374655677, 0.774795104738016, 0.120246912926227, 1.34954655602521, -1.1298961521627), .Names = c('(Intercept)', 'x1', 'x3', '', '', '', '', '', '', '')), rank = 3L, fitted.values = structure(c(2.08447598454963, 2.74878255284838, 3.46483046621199, 4.23261972464046, 5.0521503281338, 5.923422276692, 6.84643557031507, 7.821190209003, 8.84768619275579, 9.92592352157344), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10')), assign = 0:3, qr = structure(list( qr = structure(c(-3.16227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, -17.3925271309261, 9.08295106229247, 0.15621147358221, 0.0461150970695743, -0.0639812794430617, -0.174077655955698, -0.284174032468334, -0.39427040898097, -0.504366785493606, -0.614463162006242, -12.1747689916483, 9.99124616852172, 2.29782505861521, 0.388354773181155, 0.471167347118467, 0.46694109307793, 0.375676011059543, 0.197372101063308, -0.0679706369107753, -0.420352202862709, -17.3925271309261, 9.08295106229247, 1.30962518065979e-16, -1.00907321685019e-15, 0.0501848681992808, -0.170313338748631, 0.0400139169574381, -0.419073670426332, -0.887431917453648, -0.0447724572319277), .Dim = c(10L, 4L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10'), c('(Intercept)', 'x1', 'x3', 'x2')), assign = 0:3), qraux = c(1.31622776601684, 1.26630785009485, 1.21850337126599, 1.04136435435488 ), pivot = c(1L, 2L, 4L, 3L), tol = 1e-07, rank = 3L), .Names = c('qr', 'qraux', 'pivot', 'tol', 'rank'), class = 'qr'), df.residual = 7L, xlevels = structure(list(), .Names = character(0)), call = quote(lm(formula = y ~ x1 + x2 + x3)), terms = quote(y ~ x1 + x2 + x3), model = structure(list(y = c(2.30923841792462, 3.23011719303818, 2.9161246695212, 3.35931329373059, 5.3777049208621, 5.63518136825043, 7.37725908636056, 7.75621985157329, 10.1175871700049, 8.86877085545769), x1 = 1:10, x2 = 1:10, x3 = c(0.1, 0.4, 0.9, 1.6, 2.5, 3.6, 4.9, 6.4, 8.1, 10)), .Names = c('y', 'x1', 'x2', 'x3'), terms = quote(y ~ x1 + x2 + x3), row.names = c(NA, 10L), class = 'data.frame')), .Names = c('coefficients', 'residuals', 'effects', 'rank', 'fitted.values', 'assign', 'qr', 'df.residual', 'xlevels', 'call', 'terms', 'model'), class = 'lm'));`(`(argv[[1]]); Call: @@ -37609,7 +41252,7 @@ logical(0) [4,] 0.9639849-0.0000000i -0.28432636+0.08075397i [5,] -0.2883506-0.1520081i 0.06831370+0.09270951i -##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators324#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators324# #argv <- list(c(0, 0, 0, 0, 0, 0, 4.94065645841247e-324, 0, 0, 0, 0, 0), structure(c(73.0102287440125, 79.6161885135717, 81.5497837663961, 53.9710956454646, 43.6831159601594, 20.8581884349194, 7.6155030786098, 10.8008470888011, 14.7201505829463, 8.49167208457355, 101.686214382123, 921.711710792497), .Names = c('1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1')));`%*%`(argv[[1]],argv[[2]]); [,1] [1,] 3.952525e-323 @@ -37677,7 +41320,7 @@ TRUE TRUE TRUE TRUE #argv <- list(34, 2L);`%/%`(argv[[1]],argv[[2]]); [1] 17 -##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators33#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators33# #argv <- list(c(20.8, 11.2, 6.2, 12.8, 43.4), c(10.4, 5.6, 3.1, 6.4, 21.7, 0, 10.4, 5.6, 3.1, 6.4, 21.7));`+`(argv[[1]],argv[[2]]); [1] 31.2 16.8 9.3 19.2 65.1 20.8 21.6 11.8 15.9 49.8 42.5 Warning message: @@ -39236,6 +42879,11 @@ $ts.eps #order(c('40 50', '405', '40 51', '4028', '40 20', '40 30', '404')) [1] 5 6 1 3 4 7 2 +##com.oracle.truffle.r.test.builtins.TestBuiltin_order.testOrder# +#order(c(1,2,0), decreasing=NA) +Error in order(c(1, 2, 0), decreasing = NA) : + 'decreasing' must be TRUE or FALSE + ##com.oracle.truffle.r.test.builtins.TestBuiltin_order.testOrder# #{ order() } NULL @@ -39612,7 +43260,7 @@ expression(NULL) #.Internal(parse(stdin(), c(1,2), c('expr1', 'expr2'), '?', '<weird-text', 'unknown')) expression(expr1) -##com.oracle.truffle.r.test.builtins.TestBuiltin_parse.testParseDataFrame#Ignored.ImplementationError# +##com.oracle.truffle.r.test.builtins.TestBuiltin_parse.testParseDataFrame# #eval(parse(text=deparse(data.frame(x=c(1))))) x 1 1 @@ -39933,11 +43581,11 @@ character(0) #argv <- list(list(), NULL); .Internal(paste0(argv[[1]], argv[[2]])) character(0) -##com.oracle.truffle.r.test.builtins.TestBuiltin_pathexpand.testArgsValidation#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_pathexpand.testArgsValidation# #path.expand(42) Error in path.expand(42) : invalid 'path' argument -##com.oracle.truffle.r.test.builtins.TestBuiltin_pathexpand.testArgsValidation#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_pathexpand.testArgsValidation# #path.expand(NULL) Error in path.expand(NULL) : invalid 'path' argument @@ -39970,7 +43618,7 @@ character(0) #pmatch(1:5, c(1,3), duplicates.ok=42) [1] 1 NA 2 NA NA -##com.oracle.truffle.r.test.builtins.TestBuiltin_pmatch.testArgumentsCasts#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmatch.testArgumentsCasts# #pmatch(1:5, c(1,3), nomatch='str') [1] 1 NA 2 NA NA Warning message: @@ -39984,6 +43632,18 @@ In pmatch(1:5, c(1, 3), nomatch = "str") : NAs introduced by coercion #pmatch(NULL, 1) integer(0) +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmatch.testArgumentsCasts# +#pmatch(table=1) +Error in pmatch(table = 1) : argument "x" is missing, with no default + +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmatch.testArgumentsCasts# +#pmatch(x=1) +Error in pmatch(x = 1) : argument "table" is missing, with no default + +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmatch.testArgumentsCasts# +#pmatch(x=NULL, table=NULL) +integer(0) + ##com.oracle.truffle.r.test.builtins.TestBuiltin_pmatch.testpmatch1# #argv <- list('kendall', c('pearson', 'kendall', 'spearman'), 0L, TRUE); .Internal(pmatch(argv[[1]], argv[[2]], argv[[3]], argv[[4]])) [1] 2 @@ -40016,11 +43676,11 @@ integer(0) #argv <- list(character(0), c('labels', 'col', 'alpha', 'adj', 'cex', 'lineheight', 'font'), NA_integer_, TRUE); .Internal(pmatch(argv[[1]], argv[[2]], argv[[3]], argv[[4]])) integer(0) -##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax# #{ pmax(7+42i) } Error in pmax(7 + (0+42i)) : invalid input type -##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax# #{ pmax(as.raw(42)) } Error in pmax(as.raw(42)) : invalid input type @@ -40040,7 +43700,7 @@ Error in pmax(as.raw(42)) : invalid input type #{ pmax(c("1", "7"), character()) } character(0) -##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax# #{ pmax(c("1", "7", "8"), c("1"), c("42", "1")) } [1] "42" "7" "8" Warning message: @@ -40071,7 +43731,7 @@ In pmax(c("1", "7", "8"), c("1"), c("42", "1")) : #{ pmax(c(1, 7), double()) } numeric(0) -##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax# #{ pmax(c(1, 7, 8), c(1), c(42, 1)) } [1] 42 7 42 Warning message: @@ -40094,7 +43754,7 @@ In pmax(c(1, 7, 8), c(1), c(42, 1)) : #{ pmax(c(1L, 7L), integer()) } integer(0) -##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax# #{ pmax(c(1L, 7L, 8L), c(1L), c(42L, 1L)) } [1] 42 7 42 Warning message: @@ -40220,11 +43880,11 @@ Error in pmin(c(1, 2), c(3, 0), na.rm = NA) : invalid 'na.rm' value #pmin(c(1,2), c(3,NA), na.rm=c(42, 0)) [1] 1 2 -##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin# #{ pmin(7+42i) } Error in pmin(7 + (0+42i)) : invalid input type -##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin# #{ pmin(as.raw(42)) } Error in pmin(as.raw(42)) : invalid input type @@ -40244,7 +43904,7 @@ Error in pmin(as.raw(42)) : invalid input type #{ pmin(c("1", "7"), character()) } character(0) -##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin# #{ pmin(c("1", "7", "8"), c("1"), c("42", "1")) } [1] "1" "1" "1" Warning message: @@ -40275,7 +43935,7 @@ In pmin(c("1", "7", "8"), c("1"), c("42", "1")) : #{ pmin(c(1, 7), double()) } numeric(0) -##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin# #{ pmin(c(1, 7, 8), c(1), c(42, 1)) } [1] 1 1 1 Warning message: @@ -40298,7 +43958,7 @@ In pmin(c(1, 7, 8), c(1), c(42, 1)) : #{ pmin(c(1L, 7L), integer()) } integer(0) -##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin# #{ pmin(c(1L, 7L, 8L), c(1L), c(42L, 1L)) } [1] 1 1 1 Warning message: @@ -40474,7 +44134,7 @@ $n [1] 1 -##com.oracle.truffle.r.test.builtins.TestBuiltin_primUntrace.testArgsCasts#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_primUntrace.testArgsCasts# #.primUntrace(42) Error in .primUntrace(42) : argument must be a function @@ -40744,7 +44404,7 @@ $summary [13] -0.80942879 1.39969713 0.43065679 0.19581825 -0.06228429 0.57841339 [19] 2.31951400 2.93765524 -##com.oracle.truffle.r.test.builtins.TestBuiltin_print.testprint5#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_print.testprint5# #argv <- structure(list(x = structure(list(statistic = structure(0.87901108669074, .Names = 't'), parameter = structure(19, .Names = 'df'), p.value = 0.390376937081292, conf.int = structure(c(-0.332667989442433, 0.814407243771461), conf.level = 0.95), estimate = structure(0.240869627164514, .Names = 'mean of x'), null.value = structure(0, .Names = 'mean'), alternative = 'two.sided', method = 'One Sample t-test', data.name = 'x'), .Names = c('statistic', 'parameter', 'p.value', 'conf.int', 'estimate', 'null.value', 'alternative', 'method', 'data.name'), class = 'htest')), .Names = 'x');do.call('print', argv) One Sample t-test @@ -41014,7 +44674,7 @@ x3 0.81 -0.97 - x2 1 26.79 74.76 28.742 - x1 1 820.91 868.88 60.629 -##com.oracle.truffle.r.test.builtins.TestBuiltin_printdefault.testprintdefault3#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_printdefault.testprintdefault3# #argv <- list(structure(c('1', '2', '\\b', '4', '5', '\\040', '\\x20', 'c:\\spencer\\tests', '\\t', '\\n', '\\r'), .Dim = c(11L, 1L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'), 'TEST')), NULL, FALSE, NULL, NULL, TRUE, NULL, TRUE, FALSE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) TEST 1 1 @@ -41061,7 +44721,7 @@ c 535 595 655 715 #argv <- list(quote(y ~ A:U + A:V - 1), NULL, TRUE, NULL, NULL, FALSE, NULL, TRUE, TRUE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) y ~ A:U + A:V - 1 -##com.oracle.truffle.r.test.builtins.TestBuiltin_printdefault.testprintdefault7#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_printdefault.testprintdefault7# #argv <- list(structure(c(NA, NA, NA, 'a', NA, NA, 'b', 'd', NA, '10', '12', '14'), .Dim = 3:4), NULL, TRUE, '----', NULL, TRUE, NULL, TRUE, FALSE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]])) [,1] [,2] [,3] [,4] [1,] ---- "a" "b" "10" @@ -41198,6 +44858,42 @@ age 0.00561 0.012 0.00872 0.22 1.0 0.64000 sex -1.65487 0.483 0.38527 11.74 1.0 0.00061 frailty(id, dist = 't', c 20.33 13.9 0.12000 +##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd# +#{prod('a')} +Error in prod("a") : invalid 'type' (character) of argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd# +#{prod()} +[1] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd# +#{prod(2+3i,42)} +[1] 84+126i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd# +#{prod(2+3i,42+5i)} +[1] 69+136i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd# +#{prod(2+3i,c())} +[1] 2+3i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd# +#{prod(42,2+3i)} +[1] 84+126i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd# +#{prod(NULL)} +[1] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd# +#{prod(c())} +[1] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd# +#{prod(c(),c())} +[1] 1 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd# #{prod(c(1+2i))} [1] 1+2i @@ -41230,6 +44926,10 @@ frailty(id, dist = 't', c 20.33 13.9 0.12000 #{prod(c(TRUE, TRUE))} [1] 1 +##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd# +#{prod(list())} +Error in prod(list()) : invalid 'type' (list) of argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProdNa#Ignored.Unknown# #{prod(c(1,2,3,4,5,NA),FALSE)} [1] NA @@ -41349,6 +45049,18 @@ Evaluation city centre suburbs Warning message: NaNs produced +##com.oracle.truffle.r.test.builtins.TestBuiltin_psort.testArgsCasts# +#{ .Internal(psort(as.raw(c(0x44,0x40)), FALSE)) } +Error: raw vectors cannot be sorted + +##com.oracle.truffle.r.test.builtins.TestBuiltin_psort.testArgsCasts# +#{ .Internal(sort(NULL, FALSE)) } +NULL + +##com.oracle.truffle.r.test.builtins.TestBuiltin_psort.testArgsCasts# +#{ lv<-list(a=5,b=c(1,2)); .Internal(sort(lv,FALSE)) } +Error: only atomic vectors can be sorted + ##com.oracle.truffle.r.test.builtins.TestBuiltin_psort.testpsort1# #argv <- list(7:8, 1:2); .Internal(psort(argv[[1]], argv[[2]])) [1] 7 8 @@ -41583,7 +45295,7 @@ attr(,"class") #{ x <- qr(c(3,1,2), LAPACK=TRUE) ; round( qr.coef(x, c(1,3,2)), digits=5 ) } [1] 0.71429 -##com.oracle.truffle.r.test.builtins.TestBuiltin_qr.testQr#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_qr.testQr# #{ x <- qr(cbind(1:10,2:11), LAPACK=TRUE) ; qr.coef(x, 1:2) } Error in qr.coef(x, 1:2) : right-hand side should have 10 not 2 rows @@ -41653,6 +45365,18 @@ Error in qr.coef(x, 1:2) : right-hand side should have 10 not 2 rows [19,] -0.195065684 0.49023013 [20,] 0.262976528 -0.17049944 +##com.oracle.truffle.r.test.builtins.TestBuiltin_qsort.testArgsCasts#Output.IgnoreErrorMessage# +#{ .Internal(qsort(as.raw(c(0x44,0x40)), FALSE)) } +Error: argument is not a numeric vector + +##com.oracle.truffle.r.test.builtins.TestBuiltin_qsort.testArgsCasts# +#{ .Internal(sort(NULL, FALSE)) } +NULL + +##com.oracle.truffle.r.test.builtins.TestBuiltin_qsort.testArgsCasts# +#{ lv<-list(a=5,b=c(1,2)); .Internal(sort(lv,FALSE)) } +Error: only atomic vectors can be sorted + ##com.oracle.truffle.r.test.builtins.TestBuiltin_qsort.testqsort1# #argv <- list(3L, FALSE); .Internal(qsort(argv[[1]], argv[[2]])) [1] 3 @@ -41729,10 +45453,14 @@ $ix ##com.oracle.truffle.r.test.builtins.TestBuiltin_quit.testQuitEmptyEnv# #{ quit("yes") } -##com.oracle.truffle.r.test.builtins.TestBuiltin_quit.testQuitErrorSave# +##com.oracle.truffle.r.test.builtins.TestBuiltin_quit.testQuitErrorSave#Output.ImprovedErrorContext# #{ quit("xx") } Error in quit(save, status, runLast) : unrecognized value of 'save' +##com.oracle.truffle.r.test.builtins.TestBuiltin_quote.testQuote#Ignored.ImplementationError# +#quote() +Error in quote() : 0 arguments passed to 'quote' which requires 1 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_quote.testQuote# #quote(?'+') `?`("+") @@ -41749,6 +45477,10 @@ Error in quit(save, status, runLast) : unrecognized value of 'save' #quote(?sum) `?`(sum) +##com.oracle.truffle.r.test.builtins.TestBuiltin_quote.testQuote# +#quote(expr=) + + ##com.oracle.truffle.r.test.builtins.TestBuiltin_quote.testQuote# #{ class(quote(x + y)) } [1] "call" @@ -43562,6 +47294,34 @@ attr(,"useBytes") #rep(x<-42) [1] 42 +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep# +#v <- 1; class(v) <- 'asdf'; names(v) <- 'asdf'; rep(v, 1) +asdf + 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep# +#v <- 1; class(v) <- 'asdf'; names(v) <- 'asdf'; rep(v, 2) +asdf asdf + 1 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep# +#v <- 1; class(v) <- 'asdf'; rep(v, 1) +[1] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep# +#v <- 1; class(v) <- 'asdf'; rep(v, 2) +[1] 1 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep# +#v <- 1; names(v) <- 'asdf'; rep(v, 1) +asdf + 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep# +#v <- 1; names(v) <- 'asdf'; rep(v, 2) +asdf asdf + 1 1 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep# #{ rep("hello", 3) } [1] "hello" "hello" "hello" @@ -43622,14 +47382,14 @@ In rep(7, each = integer()) : first element used of 'each' argument Warning message: In rep(7, length.out = NULL) : first element used of 'length.out' argument -##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep# #{ rep(7, length.out=c(7, 42)) } [1] 7 7 7 7 7 7 7 Warning message: In rep(7, length.out = c(7, 42)) : first element used of 'length.out' argument -##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep# #{ rep(7, length.out=integer()) } [1] 7 Warning message: @@ -43774,6 +47534,14 @@ Levels: a b [1] a b a a b a a b a Levels: a b +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRepLenNull# +#rep_len(NULL,0) +NULL + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRepLenNull# +#rep_len(NULL,2) +Error in rep_len(NULL, 2) : cannot replicate NULL to a non-zero length + ##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testrep1# #argv <- list(NA, 7); .Internal(rep_len(argv[[1]], argv[[2]])) [1] NA NA NA NA NA NA NA @@ -44163,7 +47931,11 @@ character(0) #{ rep.int(7, "7") } [1] 7 7 7 7 7 7 7 -##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt# +#{ rep.int(7, -4) } +Error in rep.int(7, -4) : invalid 'times' value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt# #{ rep.int(7, NA) } Error in rep.int(7, NA) : invalid 'times' value @@ -44171,7 +47943,7 @@ Error in rep.int(7, NA) : invalid 'times' value #{ rep.int(7, NULL) } Error in rep.int(7, NULL) : incorrect type for second argument -##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt# #{ rep.int(7, c(7, 42)) } Error in rep.int(7, c(7, 42)) : invalid 'times' value @@ -44191,7 +47963,7 @@ numeric(0) #{ rep.int(c(1,2),2) } [1] 1 2 1 2 -##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt# #{ rep.int(c(1,2,3),c(2,8)) } Error in rep.int(c(1, 2, 3), c(2, 8)) : invalid 'times' value @@ -44199,6 +47971,14 @@ Error in rep.int(c(1, 2, 3), c(2, 8)) : invalid 'times' value #{ rep.int(c(1,2,3),c(2,8,3)) } [1] 1 1 2 2 2 2 2 2 2 2 3 3 3 +##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt# +#{ rep.int(c(7,1), c(1,-4)) } +Error in rep.int(c(7, 1), c(1, -4)) : invalid 'times' value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt# +#{ rep.int(c(7,1), c(1,4,5)) } +Error in rep.int(c(7, 1), c(1, 4, 5)) : invalid 'times' value + ##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt#Output.IgnoreErrorContext# #{ rep.int(function() 42, 7) } Error in rep.int(function() 42, 7) : @@ -44212,6 +47992,30 @@ Error in rep.int(function() 42, 7) : #{ rep_int(7, function() 42) } Error: could not find function "rep_int" +##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepIntComplex# +#{ rep.int(c(1+2i,100-400i,20+30i), c(3,-7)) } +Error in rep.int(c(1 + (0+2i), 100 - (0+400i), 20 + (0+30i)), c(3, -7)) : + invalid 'times' value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepIntComplex# +#{ rep.int(c(1+2i,100-400i,20+30i), c(3,7)) } +Error in rep.int(c(1 + (0+2i), 100 - (0+400i), 20 + (0+30i)), c(3, 7)) : + invalid 'times' value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepIntComplex# +#{ rep.int(c(1+2i,100-400i,20+30i), c(3,7,2)) } + [1] 1+ 2i 1+ 2i 1+ 2i 100-400i 100-400i 100-400i 100-400i 100-400i + [9] 100-400i 100-400i 20+ 30i 20+ 30i + +##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepIntComplex# +#{ rep.int(c(1+2i,20+30i,100-400i), -3) } +Error in rep.int(c(1 + (0+2i), 20 + (0+30i), 100 - (0+400i)), -3) : + invalid 'times' value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepIntComplex# +#{ rep.int(c(1+2i,20+30i,100-400i), 2) } +[1] 1+ 2i 20+ 30i 100-400i 1+ 2i 20+ 30i 100-400i + ##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testrepint1# #argv <- list(1, 6); .Internal(rep.int(argv[[1]], argv[[2]])) [1] 1 1 1 1 1 1 @@ -44436,6 +48240,18 @@ logical(0) #argv <- structure(list(x = c('#FF0000FF', '#FFFF00FF', '#00FF00FF')), .Names = 'x');do.call('rev', argv) [1] "#00FF00FF" "#FFFF00FF" "#FF0000FF" +##com.oracle.truffle.r.test.builtins.TestBuiltin_rhyper.testNullAndMissing# +#rmultinom(0,0,0) +Error in rmultinom(0, 0, 0) : no positive probabilities + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rhyper.testNullAndMissing# +#rmultinom(0,0,0,NULL) +Error in rmultinom(0, 0, 0, NULL) : unused argument (NULL) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rhyper.testSimple# +#rhyper(0,0,0,0) +integer(0) + ##com.oracle.truffle.r.test.builtins.TestBuiltin_rm.basicTests# # e <- new.env(); e$a <- 42; rm(list='a', envir=e); e$a NULL @@ -44468,6 +48284,19 @@ Error in rm(tmp, envir = NULL) : use of NULL environment is defunct #tmp <- 42; rm(tmp, inherits='asd') Error in rm(tmp, inherits = "asd") : invalid 'inherits' argument +##com.oracle.truffle.r.test.builtins.TestBuiltin_rmultinom.testNullAndMissing# +#rmultinom(1, 1) +Error in rmultinom(1, 1) : argument "prob" is missing, with no default + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rmultinom.testNullAndMissing# +#rmultinom(1, 1, NULL) +Error in rmultinom(1, 1, NULL) : no positive probabilities + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rmultinom.testSimple# +#rmultinom(1,1,1) + [,1] +[1,] 1 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_round.testRound# #{ round(-1.5) } [1] -2 @@ -44872,6 +48701,39 @@ numeric(0) #argv <- structure(list(x = structure(list(x = 3:4), .Names = 'x', row.names = c(NA, -2L), class = 'data.frame')), .Names = 'x');do.call('row.names.data.frame', argv) [1] "1" "2" +##com.oracle.truffle.r.test.builtins.TestBuiltin_rowsum.testRowsumArgCoverage# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("Error in rowsum_matrix(x, NULL, ug, FALSE, as.character(ug)) :\n invalid 'g' argument" } else { x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, NULL, ug, FALSE,as.character(ug))) } +Error: unexpected '}' in "if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("Error in rowsum_matrix(x, NULL, ug, FALSE, as.character(ug)) :\n invalid 'g' argument" }" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rowsum.testRowsumArgCoverage# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("Error in rowsum_matrix(x, print, ug, FALSE, as.character(ug)) :\n invalid 'g' argument" } else { { x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, print, ug, FALSE, as.character(ug))); } } +Error: unexpected '}' in "if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("Error in rowsum_matrix(x, print, ug, FALSE, as.character(ug)) :\n invalid 'g' argument" }" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rowsum.testRowsumArgCoverage#Output.IgnoreErrorMessage# +#x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, , ug, FALSE,as.character(ug))) +Error in .Internal(rowsum_matrix(x, , ug, FALSE, as.character(ug))) : + argument 2 is empty + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rowsum.testRowsumArgCoverage#Output.IgnoreErrorMessage# +#x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, , FALSE,as.character(ug))) +Error in .Internal(rowsum_matrix(x, g, , FALSE, as.character(ug))) : + argument 3 is empty + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rowsum.testRowsumArgCoverage#Output.IgnoreErrorMessage# +#x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, NULL, FALSE,as.character(ug))) +Error: unimplemented type 'NULL' in 'HashTableSetup' + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rowsum.testRowsumArgCoverage#Output.IgnoreErrorMessage# +#x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, print, FALSE, as.character(ug))) +Error: unimplemented type 'closure' in 'HashTableSetup' + +##com.oracle.truffle.r.test.builtins.TestBuiltin_rowsum.testRowsumArgCoverage# +#x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, ug, FALSE, as.character(ug))) + [,1] [,2] +1 6 16 +2 6 16 +3 3 8 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_rowsum.testrowsum1# #argv <- list(structure(1:12, .Dim = 3:4), c('Y', 'X', 'Y'), c('X', 'Y'), FALSE, c('X', 'Y')); .Internal(rowsum_matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]])) [,1] [,2] [,3] [,4] @@ -45040,10 +48902,30 @@ Error: invalid first argument #set.seed(42); .Internal(sample(4.5e20, 4.5e20, FALSE, NULL)) Error: vector size specified is too large +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts#Output.IgnoreErrorMessage# +#set.seed(42); .Internal(sample(5,6,T,)) +Error in .Internal(sample(5, 6, T, )) : argument 4 is empty + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts# +#set.seed(42); .Internal(sample(5,6,T,NULL)) +[1] 5 5 2 5 4 3 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts#Output.IgnoreErrorMessage# +#set.seed(42); .Internal(sample(5,6,T,seq(1.2,3))) +Error: incorrect number of probabilities + ##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts# #set.seed(42); .Internal(sample(NA, NA, FALSE, NULL)) Error: invalid first argument +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts# +#set.seed(42); .Internal(sample(NULL, NULL, F, NULL)) +Error: invalid first argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts# +#set.seed(42); .Internal(sample(NULL, NULL, F, seq(1.2,3))) +Error: invalid first argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts# #set.seed(42); .Internal(sample(NaN, NaN, FALSE, NULL)) Error: vector size cannot be NA/NaN @@ -45084,11 +48966,11 @@ Error in sample.int(x, size, replace, prob) : invalid 'size' argument #set.seed(42); sample(3, c(2,3)) [1] 3 2 -##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts# #set.seed(42); sample(4, prob=c(-1,1,1,2)) Error in sample.int(x, size, replace, prob) : negative probability -##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts# #set.seed(42); sample(4, prob=c(1,2)) Error in sample.int(x, size, replace, prob) : incorrect number of probabilities @@ -45105,7 +48987,7 @@ Error in !replace : invalid argument type #set.seed(42); sample(4, replace=1.2) [1] 4 4 2 4 -##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts# #set.seed(42); sample(4, replace=c(T,F)) Error in sample.int(x, size, replace, prob) : invalid 'replace' argument @@ -45279,6 +49161,10 @@ Error: invalid first argument [1] 3794143200 1186759075 2661629063 3054987943 2724864852 1898476583 [7] 3876537848 1917352029 4057178109 1970042664 +##com.oracle.truffle.r.test.builtins.TestBuiltin_sample2.testSample2# +#set.seed(42); .Internal(sample2(NULL,3)) +Error: invalid first argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_sample2.testSample2# #set.seed(42); x <- .Internal(sample2(10L, 3L)); y <- .Internal(sample2(10L, 3L)); list(x, y); [[1]] @@ -45319,6 +49205,33 @@ attr(,"scaled:scale") [1] 0.3602647 0.2569776 0.2098340 0.2739593 0.2779866 0.2412907 0.3059602 [8] 0.3354207 0.3088318 +##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testArgsCasts#Output.IgnoreErrorContext# +#{ con<-textConnection(c("1 2 3", "4 5 6")); .Internal(scan(con, , 2, ' ', '.', '"', 0, 3, "NA", F, F, F, T, T, '', '#', T, 'utf8', F)) } +Error in .Internal(scan(con, , 2, " ", ".", "\"", 0, 3, "NA", F, F, F, : + argument 2 is empty + +##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testArgsCasts# +#{ con<-textConnection(c("1 2 3", "4 5 6")); .Internal(scan(con, 1L, 2, NULL, '.', '"', 0, 3, "NA", F, F, F, T, T, '', '#', T, 'utf8', F)) } +[1] 1 2 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testArgsCasts# +#{ con<-textConnection(c("1 2 3", "4 5 6")); .Internal(scan(con, NULL, 2, ' ', '.', '"', 0, 3, "NA", F, F, F, T, T, '', '#', T, 'utf8', F)) } +Error: invalid 'what' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testArgsCasts# +#{ con<-textConnection(c("1 2 3", "4 5 6")); .Internal(scan(con, print, 2, ' ', '.', '"', 0, 3, "NA", F, F, F, T, T, '', '#', T, 'utf8', F)) } +Error: invalid 'what' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testArgsCasts# +#{ con<-textConnection(c("1.5 2.89 3", "4 5 6")); .Internal(scan(con, 1.2, 2, ' ', NULL, '"', 0, 3, "NA", F, F, F, T, T, '', '#', T, 'utf8', F)) } +[1] 1.50 2.89 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testScan# +#con <- textConnection("A|B|C\n1|2|3\n4|5|6"); read.csv(con, sep="|") + A B C +1 1 2 3 +2 4 5 6 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testScan# #{ con<-textConnection(c("'foo'")); scan(con, what=list("")) } Read 1 record @@ -45361,7 +49274,7 @@ Read 3 items #{ con<-textConnection(c("HEADER", "7 2 3", "4 5 42")); scan(con, skip = 1, quiet=TRUE) } [1] 7 2 3 4 5 42 -##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testScan#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testScan# #{ con<-textConnection(c("HEADER", "7 2 3", "4 5 42")); scan(con, what = list("","","")) } Read 3 records [[1]] @@ -45403,7 +49316,7 @@ Read 3 records [1] "" "3" "42" -##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testScan#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testScan# #{ con<-textConnection(c("HEADER", "7 2 3", "4 5 42")); scan(con, what = list("","",""), multi.line=FALSE) } Error in scan(con, what = list("", "", ""), multi.line = FALSE) : line 1 did not have 3 elements @@ -45422,7 +49335,7 @@ Read 4 items #{ con<-textConnection(c("TITLE extra line", "2 3 5 7", "11 13 17")); scan(con, skip = 1, quiet = TRUE) } [1] 2 3 5 7 11 13 17 -##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testScan#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testScan# #{ con<-textConnection(c("TITLE extra line", "2 3 5 7", "11 13 17")); scan(con, what = list("","","")) } Read 4 records [[1]] @@ -45506,7 +49419,7 @@ Read 2 records #argv <- list(1, 1);`/`(argv[[1]],argv[[2]]); [1] 1 -##com.oracle.truffle.r.test.builtins.TestBuiltin_sep.testsep10#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_sep.testsep10# #argv <- list(c(0, 9.88131291682493e-324, 1.03753785626662e-322, 1.02271588689138e-321, 1.02320995253722e-320, 1.02330876566639e-319, 1.02329394369701e-318, 1.02329295556572e-317, 1.02329300497229e-316, 1.02329299015032e-315, 1.02329299212658e-314, 1.0232929922748e-313, 1.02329299227974e-312, 1.02329299228073e-311, 1.02329299228073e-310, 1.02329299228073e-309, 1.02329299228073e-308, 1.02329299228073e-307), 1.02329299228075);`/`(argv[[1]],argv[[2]]); [1] 0.000000e+00 9.881313e-324 1.037538e-322 9.980126e-322 9.999889e-321 [6] 1.000038e-319 9.999987e-319 9.999997e-318 1.000000e-316 1.000000e-315 @@ -58169,7 +62082,7 @@ integer(0) [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 [26] 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 -##com.oracle.truffle.r.test.builtins.TestBuiltin_seq_along.testWithNonStandardLength#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_seq_along.testWithNonStandardLength#Output.IgnoreWarningContext#Output.IgnoreErrorContext# #{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) 'hello world'; seq_along(x) } Error: negative length vectors are not allowed In addition: Warning message: @@ -58189,7 +62102,7 @@ NAs introduced by coercion [73] 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 [91] 91 92 93 94 95 96 97 98 99 100 -##com.oracle.truffle.r.test.builtins.TestBuiltin_seq_along.testWithNonStandardLength# +##com.oracle.truffle.r.test.builtins.TestBuiltin_seq_along.testWithNonStandardLength#Output.IgnoreWarningContext#Output.IgnoreErrorContext# #{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) numeric(0); seq_along(x) } Error: negative length vectors are not allowed @@ -58489,6 +62402,119 @@ 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.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 + [26] 01 00 04 00 09 00 00 00 09 63 6c 61 73 73 4e 61 6d 65 00 00 02 10 00 00 00 + [51] 01 00 04 00 09 00 00 00 0a 46 6f 6f 53 65 72 69 61 6c 31 00 00 04 02 00 00 + [76] 00 01 00 04 00 09 00 00 00 07 70 61 63 6b 61 67 65 00 00 00 10 00 00 00 01 +[101] 00 04 00 09 00 00 00 0a 2e 47 6c 6f 62 61 6c 45 6e 76 00 00 00 fe 00 00 04 +[126] 02 00 00 02 ff 00 00 00 10 00 00 00 01 00 04 00 09 00 00 00 0a 2e 47 6c 6f +[151] 62 61 6c 45 6e 76 00 00 04 02 00 00 00 01 00 04 00 09 00 00 00 05 63 6c 61 +[176] 73 73 00 00 02 10 00 00 00 01 00 04 00 09 00 00 00 16 63 6c 61 73 73 47 65 +[201] 6e 65 72 61 74 6f 72 46 75 6e 63 74 69 6f 6e 00 00 04 02 00 00 02 ff 00 00 +[226] 00 10 00 00 00 01 00 04 00 09 00 00 00 07 6d 65 74 68 6f 64 73 00 00 00 fe +[251] 00 00 00 fe 00 00 00 fd 00 00 04 02 00 00 00 01 00 04 00 09 00 00 00 03 2e +[276] 2e 2e 00 00 00 fb 00 00 00 fe 00 00 00 06 00 00 00 01 00 04 00 09 00 00 00 +[301] 03 6e 65 77 00 00 00 02 00 00 02 10 00 00 00 01 00 04 00 09 00 00 00 0a 46 +[326] 6f 6f 53 65 72 69 61 6c 31 00 00 04 02 00 00 02 ff 00 00 00 10 00 00 00 01 +[351] 00 04 00 09 00 00 00 0a 2e 47 6c 6f 62 61 6c 45 6e 76 00 00 00 fe 00 00 00 +[376] 06 00 00 04 ff 00 00 00 fe + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); mc <- setClass('FooSerial0', representation(a = 'call')); obj <- new('FooSerial0'); serialize(obj, connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 01 03 19 00 00 04 02 00 00 00 + [26] 01 00 04 00 09 00 00 00 01 61 00 00 00 06 00 00 00 01 00 04 00 09 00 00 00 + [51] 07 3c 75 6e 64 65 66 3e 00 00 00 fe 00 00 04 02 00 00 00 01 00 04 00 09 00 + [76] 00 00 05 63 6c 61 73 73 00 00 02 10 00 00 00 01 00 04 00 09 00 00 00 0a 46 +[101] 6f 6f 53 65 72 69 61 6c 30 00 00 04 02 00 00 00 01 00 04 00 09 00 00 00 07 +[126] 70 61 63 6b 61 67 65 00 00 00 10 00 00 00 01 00 04 00 09 00 00 00 0a 2e 47 +[151] 6c 6f 62 61 6c 45 6e 76 00 00 00 fe 00 00 00 fe + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); serialize('asdf', connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 10 00 00 00 01 00 04 00 +[26] 09 00 00 00 04 61 73 64 66 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); serialize(111+8i, connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0f 00 00 00 01 40 5b c0 +[26] 00 00 00 00 00 40 20 00 00 00 00 00 00 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); serialize(111, connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0e 00 00 00 01 40 5b c0 +[26] 00 00 00 00 00 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); serialize(111L, connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0d 00 00 00 01 00 00 00 +[26] 6f + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); serialize(FALSE, connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0a 00 00 00 01 00 00 00 +[26] 00 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); serialize(NA_character_, connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 10 00 00 00 01 00 00 00 +[26] 09 ff ff ff ff + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); serialize(NA_complex_, connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0f 00 00 00 01 7f f0 00 +[26] 00 00 00 07 a2 7f f0 00 00 00 00 07 a2 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); serialize(NA_integer_, connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0d 00 00 00 01 80 00 00 +[26] 00 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); serialize(NA_real_, connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0e 00 00 00 01 7f f0 00 +[26] 00 00 00 07 a2 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); serialize(TRUE, connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0a 00 00 00 01 00 00 00 +[26] 01 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); serialize(as.raw(10), connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 18 00 00 00 01 0a + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); serialize(as.raw(210), connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 18 00 00 00 01 d2 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); serialize(as.raw(c(1, 55, 210)), connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 18 00 00 00 03 01 37 d2 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); serialize(c(111+8i, 55+9i, NA), connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0f 00 00 00 03 40 5b c0 +[26] 00 00 00 00 00 40 20 00 00 00 00 00 00 40 4b 80 00 00 00 00 00 40 22 00 00 +[51] 00 00 00 00 7f f0 00 00 00 00 07 a2 7f f0 00 00 00 00 07 a2 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); serialize(c(111, 99, NA, 44), connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0e 00 00 00 04 40 5b c0 +[26] 00 00 00 00 00 40 58 c0 00 00 00 00 00 7f f0 00 00 00 00 07 a2 40 46 00 00 +[51] 00 00 00 00 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); serialize(c(111L, 11L, 990000L, NA_integer_), connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0d 00 00 00 04 00 00 00 +[26] 6f 00 00 00 0b 00 0f 1b 30 80 00 00 00 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); serialize(c(TRUE, FALSE, TRUE, NA, TRUE), connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0a 00 00 00 05 00 00 00 +[26] 01 00 00 00 00 00 00 00 01 80 00 00 00 00 00 00 01 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# #options(keep.source=FALSE); serialize(quote("bar"), connection=NULL) [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 10 00 00 00 01 00 04 00 @@ -58839,6 +62865,20 @@ integer(0) [51] 00 00 00 01 00 04 00 09 00 00 00 05 6e 61 6d 65 73 00 00 00 10 00 00 00 01 [76] 00 04 00 09 00 00 00 06 65 6e 63 6c 6f 73 00 00 00 fe +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); val <- new.env(hash=FALSE); makeActiveBinding('a', function(x) print('hello'), val); data <- serialize(val, connection=NULL); newenv <- unserialize(rawConnection(data)); newenv$a +[1] "hello" +[1] "hello" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#options(keep.source=FALSE); val <- new.env(hash=FALSE); makeActiveBinding('a', function(x) print('hello'), val); serialize(val, connection=NULL) + [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 04 00 00 00 00 00 00 00 + [26] fd 08 00 04 02 00 00 00 01 00 04 00 09 00 00 00 01 61 00 00 04 03 00 00 00 + [51] fd 00 00 04 02 00 00 00 01 00 04 00 09 00 00 00 01 78 00 00 00 fb 00 00 00 + [76] fe 00 00 00 06 00 00 00 01 00 04 00 09 00 00 00 05 70 72 69 6e 74 00 00 00 +[101] 02 00 00 00 10 00 00 00 01 00 04 00 09 00 00 00 05 68 65 6c 6c 6f 00 00 00 +[126] fe 00 00 00 fe 00 00 00 fe 00 00 00 fe + ##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# #options(keep.source=FALSE); val <- new.env(hash=FALSE); serialize(val, connection=NULL) [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 04 00 00 00 00 00 00 00 @@ -58892,6 +62932,13 @@ integer(0) [151] 63 6b 61 67 65 00 00 00 10 00 00 00 01 00 04 00 09 00 00 00 0a 2e 47 6c 6f [176] 62 61 6c 45 6e 76 00 00 00 fe 00 00 00 fe +##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize# +#{ options(keep.source=FALSE); f <- function() NULL; attributes(f) <- list(skeleton=quote(`<undef>`())); data <- serialize(f, conn=NULL); unserialize(conn=data) } +function () +NULL +attr(,"skeleton") +`<undef>`() + ##com.oracle.truffle.r.test.builtins.TestBuiltin_setEncoding.testsetEncoding1# #argv <- list('abc', 'UTF-8'); .Internal(setEncoding(argv[[1]], argv[[2]])) [1] "abc" @@ -58962,6 +63009,10 @@ integer(0) ##com.oracle.truffle.r.test.builtins.TestBuiltin_setHook.testsetHook1#Ignored.SideEffects# #argv <- structure(list(hookName = 'UserHook::stats4::onUnload', value = function(pkgname, ...) cat('onUnload', sQuote(pkgname), 'B', '\n')), .Names = c('hookName', 'value'));do.call('setHook', argv) +##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testSetS4Object# +#{ x<-42; asS4(, TRUE, 1)) } +Error: unexpected ')' in "{ x<-42; asS4(, TRUE, 1))" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testSetS4Object# #{ x<-42; asS4(x, "TRUE") } [1] 42 @@ -59223,7 +63274,7 @@ In set.seed("hello world") : NAs introduced by coercion #.Internal(shortRowNames(42, '1')) [1] 0 -##com.oracle.truffle.r.test.builtins.TestBuiltin_shortRowNames.testArgCasts#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_shortRowNames.testArgCasts# #.Internal(shortRowNames(42, -2)) Error: invalid 'type' argument @@ -59850,6 +63901,14 @@ In sinpi(argv[[1]]) : NaNs produced [4,] -0.6666667 1.3333333 -2 2.6666667 -1.3333333 [5,] 0.3333333 -0.6666667 1 -1.3333333 1.6666667 +##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testArgsCasts# +#{ .Internal(sort(NULL, FALSE)) } +NULL + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testArgsCasts# +#{ .Internal(sort(as.raw(c(0x44,0x40)), FALSE)) } +Error: raw vectors cannot be sorted + ##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testArgsCasts# #{ .Internal(sort(c(1L,10L,2L), 'not-numeric')) } Error: 'decreasing' must be TRUE or FALSE @@ -59858,6 +63917,84 @@ Error: 'decreasing' must be TRUE or FALSE #{ .Internal(sort(c(1L,10L,2L), NULL)) } Error: 'decreasing' must be TRUE or FALSE +##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testArgsCasts# +#{ lv<-list(a=5,b=c(1,2)); .Internal(sort(lv,FALSE)) } +Error: only atomic vectors can be sorted + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort# +#{ .Internal(qsort(1, F)) } +[1] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort#Ignored.ImplementationError# +#{ .Internal(qsort(1, decreased=NULL)) } +$x +[1] 1 + +$ix +[1] 1 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort# +#{ .Internal(qsort(NULL, F)) } +Error: argument is not a numeric vector + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort# +#{ .Internal(qsort(NULL, NULL)) } +Error: argument is not a numeric vector + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort# +#{ .Internal(qsort(c(1), F)) } +[1] 1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort#Ignored.ImplementationError# +#{ .Internal(qsort(c(4, 2, 3), 'a')) } +$x +[1] 2 3 4 + +$ix +[1] 2 3 1 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort#Ignored.ImplementationError# +#{ .Internal(qsort(c(4, 2, 3), 1)) } +$x +[1] 2 3 4 + +$ix +[1] 2 3 1 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort#Ignored.ImplementationError# +#{ .Internal(qsort(c(4, 2, 3), T)) } +$x +[1] 2 3 4 + +$ix +[1] 2 3 1 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort#Ignored.ImplementationError# +#{ .Internal(qsort(c(4, 2, 3), c('a'))) } +$x +[1] 2 3 4 + +$ix +[1] 2 3 1 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort#Ignored.ImplementationError# +#{ .Internal(qsort(c(4, 2, 3), list('a'))) } +$x +[1] 2 3 4 + +$ix +[1] 2 3 1 + + +##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort# +#{ .Internal(qsort(list(1), F)) } +Error: argument is not a numeric vector + ##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testSort# #{ sort(3:1, index.return=TRUE) } $x @@ -60446,7 +64583,7 @@ $`2` 0.0000 1514.0769 0.0000 936.0000 0.0000 -##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testsplit4#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testsplit4# #argv <- list(structure(c(0, 0, 0, 0, 0, 0, 1.48219693752374e-323, 0, 0, 0, 0, 0), .Dim = c(1L, 12L), .Dimnames = list(NULL, c('1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1'))), structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = '1', class = 'factor')); .Internal(split(argv[[1]], argv[[2]])) $`1` [1] 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 @@ -61461,6 +65598,18 @@ B FALSE TRUE [2,] 1 [3,] 2 +##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.testArgsCasts# +#{ .Internal(strptime('','',) } +Error: unexpected '}' in "{ .Internal(strptime('','',) }" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.testArgsCasts# +#{ .Internal(strptime('',,'') } +Error: unexpected '}' in "{ .Internal(strptime('',,'') }" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.testArgsCasts# +#{ .Internal(strptime(,'','') } +Error: unexpected '}' in "{ .Internal(strptime(,'','') }" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.teststrptime1# #argv <- list('2008-04-22 09:45', '%Y-%m-%d', ''); .Internal(strptime(argv[[1]], argv[[2]], argv[[3]])) [1] "2008-04-22 GMT" @@ -61527,6 +65676,22 @@ character(0) [1] "1890-01-01 GMT" "1891-01-01 GMT" "1892-01-01 GMT" "1893-01-01 GMT" [5] "1894-01-01 GMT" "1895-01-01 GMT" +##com.oracle.truffle.r.test.builtins.TestBuiltin_strrep.testArgsCasts# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("character(0)") } else { { .Internal(strrep('aa', NULL) } } +Error: unexpected '}' in "if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("character(0)") } else { { .Internal(strrep('aa', NULL) }" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_strrep.testArgsCasts# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("character(0)") } else { { .Internal(strrep(NULL, 5) } } +Error: unexpected '}' in "if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("character(0)") } else { { .Internal(strrep(NULL, 5) }" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_strrep.testArgsCasts# +#{ .Internal(strrep('', ) } +Error: unexpected '}' in "{ .Internal(strrep('', ) }" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_strrep.testArgsCasts# +#{ .Internal(strrep(, '') } +Error: unexpected '}' in "{ .Internal(strrep(, '') }" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_strrep.testStrrep# #{ strrep("ABC", 2) } [1] "ABCABC" @@ -61771,7 +65936,7 @@ Error: non-character argument [1] "abc" -##com.oracle.truffle.r.test.builtins.TestBuiltin_strsplit.testStrSplit#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_strsplit.testStrSplit# #{ strsplit("abc", ".", fixed = TRUE, perl=TRUE) } [[1]] [1] "abc" @@ -61997,6 +66162,14 @@ character(0) #argv <- list(character(0), 8L); .Internal(strtoi(argv[[1]], argv[[2]])) integer(0) +##com.oracle.truffle.r.test.builtins.TestBuiltin_strtrim.testArgsCasts#Output.IgnoreErrorContext# +#.Internal(strtrim('abc', )) +Error in .Internal(strtrim("abc", )) : argument 2 is empty + +##com.oracle.truffle.r.test.builtins.TestBuiltin_strtrim.testArgsCasts# +#.Internal(strtrim('abc', NULL)) +Error: invalid 'width' argument + ##com.oracle.truffle.r.test.builtins.TestBuiltin_strtrim.teststrtrim# #v <- c('a', 'fooooo', 'bbbbbb', 'cccccccccc', 'dd', NA); names(v) <- as.character(1:6); strtrim(v, c(2, 5)) 1 2 3 4 5 6 @@ -63442,7 +67615,7 @@ if (x + y) { #{ substr(NA,1,2) } [1] NA -##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring# #{ substr(c("abcdef", "aa"), 2, integer()) } Error in substr(c("abcdef", "aa"), 2, integer()) : invalid substring arguments @@ -63463,7 +67636,7 @@ Error in substr(c("abcdef", "aa"), 2, integer()) : #{ substr(c("abcdef", "aa"), c(NA,8), 4) } [1] NA "" -##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring# #{ substr(c("abcdef", "aa"), integer(), 2) } Error in substr(c("abcdef", "aa"), integer(), 2) : invalid substring arguments @@ -63496,11 +67669,11 @@ character(0) #{ x<-"abcdef"; substr(x,1,3)<-"0000"; x } [1] "000def" -##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.ImprovedErrorContext# #{ x<-"abcdef"; substr(x,1,3)<-NULL; x } Error in `substr<-`(`*tmp*`, 1, 3, value = NULL) : invalid value -##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.ImprovedErrorContext# #{ x<-"abcdef"; substr(x,1,3)<-character(); x } Error in `substr<-`(`*tmp*`, 1, 3, value = character(0)) : invalid value @@ -63512,7 +67685,7 @@ Error in `substr<-`(`*tmp*`, 1, 3, value = character(0)) : invalid value #{ x<-"abcdef"; substr(x,1,NA)<-"0"; x } [1] NA -##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.ImprovedErrorContext# #{ x<-"abcdef"; substr(x,3,1)<-0; x } Error in `substr<-`(`*tmp*`, 3, 1, value = 0) : invalid value @@ -63520,7 +67693,7 @@ Error in `substr<-`(`*tmp*`, 3, 1, value = 0) : invalid value #{ x<-"abcdef"; substr(x,NA,3)<-"0"; x } [1] NA -##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.ImprovedErrorContext# #{ x<-"abcdef"; substr(x,integer(),3)<-NULL; x } Error in `substr<-`(`*tmp*`, integer(), 3, value = NULL) : invalid substring arguments @@ -63589,6 +67762,128 @@ model.frame predict residuals #argv <- list('> ### R code from vignette source \'parallel.Rnw\'\n> \n> ###################################################\n> ### code chunk number 1: parallel.Rnw:474-475 (eval = FALSE)\n> ###################################################\n> ## library(parallel)\n> \n> \n> ###################################################\n> ### code chunk number 2: parallel.Rnw:500-507 (eval = FALSE)\n> ###################################################\n> ## library(boot)\n> ## cd4.rg <- function(data, mle) MASS::mvrnorm(nrow(data), mle$m, mle$v)\n> ## cd4.mle <- list(m = colMeans(cd4), v = var(cd4))\n> ## cd4.boot <- boot(cd4, corr, R = 999, sim = \'parametric\',\n> ## ran.gen = cd4.rg, mle = cd4.mle)\n> ## boot.ci(cd4.boot, type = c(\'norm\', \'basic\', \'perc\'),\n> ## conf = 0.9, h = atanh, hinv = tanh)\n> \n> \n> ###################################################\n> ### code chunk number 3: parallel.Rnw:512-522 (eval = FALSE)\n> ###################################################\n> ## cd4.rg <- function(data, mle) MASS::mvrnorm(nrow(data), mle$m, mle$v)\n> ## cd4.mle <- list(m = colMeans(cd4), v = var(cd4))\n> ## run1 <- function(...) boot(cd4, corr, R = 500, sim = \'parametric\',\n> ## ran.gen = cd4.rg, mle = cd4.mle)\n> ## mc <- 2 # set as appropriate for your hardware\n> ## ## To make this reproducible:\n> ## set.seed(123, \'L\'Ecuyer\')\n> ## cd4.boot <- do.call(c, mclapply(seq_len(mc), run1) )\n> ## boot.ci(cd4.boot, type = c(\'norm\', \'basic\', \'perc\'),\n> ## conf = 0.9, h = atanh, hinv = tanh)\n> \n> \n> ###################################################\n> ### code chunk number 4: parallel.Rnw:527-528 (eval = FALSE)\n> ###################################################\n> ## do.call(c, lapply(seq_len(mc), run1))\n> \n> \n> ###################################################\n> ### code chunk number 5: parallel.Rnw:532-547 (eval = FALSE)\n> ###################################################\n> ## run1 <- function(...) {\n> ## library(boot)\n> ## cd4.rg <- function(data, mle) MASS::mvrnorm(nrow(data), mle$m, mle$v)\n> ## cd4.mle <- list(m = colMeans(cd4), v = var(cd4))\n> ## boot(cd4, corr, R = 500, sim = \'parametric\',\n> ## ran.gen = cd4.rg, mle = cd4.mle)\n> ## }\n> ## cl <- makeCluster(mc)\n> ## ## make this reproducible\n> ## clusterSetRNGStream(cl, 123)\n> ## library(boot) # needed for c() method on master\n> ## cd4.boot <- do.call(c, parLapply(cl, seq_len(mc), run1) )\n> ## boot.ci(cd4.boot, type = c(\'norm\', \'basic\', \'perc\'),\n> ## conf = 0.9, h = atanh, hinv = tanh)\n> ## stopCluster(cl)\n> \n> \n> ###################################################\n> ### code chunk number 6: parallel.Rnw:557-570 (eval = FALSE)\n> ###################################################\n> ## cl <- makeCluster(mc)\n> ## cd4.rg <- function(data, mle) MASS::mvrnorm(nrow(data), mle$m, mle$v)\n> ## cd4.mle <- list(m = colMeans(cd4), v = var(cd4))\n> ## clusterExport(cl, c(\'cd4.rg\', \'cd4.mle\'))\n> ## junk <- clusterEvalQ(cl, library(boot)) # discard result\n> ## clusterSetRNGStream(cl, 123)\n> ## res <- clusterEvalQ(cl, boot(cd4, corr, R = 500,\n> ## sim = \'parametric\', ran.gen = cd4.rg, mle = cd4.mle))\n> ## library(boot) # needed for c() method on master\n> ## cd4.boot <- do.call(c, res)\n> ## boot.ci(cd4.boot, type = c(\'norm\', \'basic\', \'perc\'),\n> ## conf = 0.9, h = atanh, hinv = tanh)\n> ## stopCluster(cl)\n> \n> \n> ###################################################\n> ### code chunk number 7: parallel.Rnw:575-589 (eval = FALSE)\n> ###################################################\n> ## R <- 999; M <- 999 ## we would like at least 999 each\n> ## cd4.nest <- boot(cd4, nested.corr, R=R, stype=\'w\', t0=corr(cd4), M=M)\n> ## ## nested.corr is a function in package boot\n> ## op <- par(pty = \'s\', xaxs = \'i\', yaxs = \'i\')\n> ## qqplot((1:R)/(R+1), cd4.nest$t[, 2], pch = \'.\', asp = 1,\n> ## xlab = \'nominal\', ylab = \'estimated\')\n> ## abline(a = 0, b = 1, col = \'grey\')\n> ## abline(h = 0.05, col = \'grey\')\n> ## abline(h = 0.95, col = \'grey\')\n> ## par(op)\n> ## \n> ## nominal <- (1:R)/(R+1)\n> ## actual <- cd4.nest$t[, 2]\n> ## 100*nominal[c(sum(actual <= 0.05), sum(actual < 0.95))]\n> \n> \n> ###################################################\n> ### code chunk number 8: parallel.Rnw:594-602 (eval = FALSE)\n> ###################################################\n> ## mc <- 9\n> ## R <- 999; M <- 999; RR <- floor(R/mc)\n> ## run2 <- function(...)\n> ## cd4.nest <- boot(cd4, nested.corr, R=RR, stype=\'w\', t0=corr(cd4), M=M)\n> ## cd4.nest <- do.call(c, mclapply(seq_len(mc), run2, mc.cores = mc) )\n> ## nominal <- (1:R)/(R+1)\n> ## actual <- cd4.nest$t[, 2]\n> ## 100*nominal[c(sum(actual <= 0.05), sum(actual < 0.95))]\n> \n> \n> ###################################################\n> ### code chunk number 9: parallel.Rnw:616-627 (eval = FALSE)\n> ###################################################\n> ## library(spatial)\n> ## towns <- ppinit(\'towns.dat\')\n> ## tget <- function(x, r=3.5) sum(dist(cbind(x$x, x$y)) < r)\n> ## t0 <- tget(towns)\n> ## R <- 1000\n> ## c <- seq(0, 1, 0.1)\n> ## ## res[1] = 0\n> ## res <- c(0, sapply(c[-1], function(c)\n> ## mean(replicate(R, tget(Strauss(69, c=c, r=3.5))))))\n> ## plot(c, res, type=\'l\', ylab=\'E t\')\n> ## abline(h=t0, col=\'grey\')\n> \n> \n> ###################################################\n> ### code chunk number 10: parallel.Rnw:631-640 (eval = FALSE)\n> ###################################################\n> ## run3 <- function(c) {\n> ## library(spatial)\n> ## towns <- ppinit(\'towns.dat\') # has side effects\n> ## mean(replicate(R, tget(Strauss(69, c=c, r=3.5))))\n> ## }\n> ## cl <- makeCluster(10, methods = FALSE)\n> ## clusterExport(cl, c(\'R\', \'towns\', \'tget\'))\n> ## res <- c(0, parSapply(cl, c[-1], run3)) # 10 tasks\n> ## stopCluster(cl)\n> \n> \n> ###################################################\n> ### code chunk number 11: parallel.Rnw:644-648 (eval = FALSE)\n> ###################################################\n> ## cl <- makeForkCluster(10) # fork after the variables have been set up\n> ## run4 <- function(c) mean(replicate(R, tget(Strauss(69, c=c, r=3.5))))\n> ## res <- c(0, parSapply(cl, c[-1], run4))\n> ## stopCluster(cl)\n> \n> \n> ###################################################\n> ### code chunk number 12: parallel.Rnw:651-653 (eval = FALSE)\n> ###################################################\n> ## run4 <- function(c) mean(replicate(R, tget(Strauss(69, c=c, r=3.5))))\n> ## res <- c(0, unlist(mclapply(c[-1], run4, mc.cores = 10)))\n> \n> \n> ###################################################\n> ### code chunk number 13: parallel.Rnw:684-718 (eval = FALSE)\n> ###################################################\n> ## pkgs <- \'<names of packages to be installed>\'\n> ## M <- 20 # number of parallel installs\n> ## M <- min(M, length(pkgs))\n> ## library(parallel)\n> ## unlink(\'install_log\')\n> ## cl <- makeCluster(M, outfile = \'install_log\')\n> ## clusterExport(cl, c(\'tars\', \'fakes\', \'gcc\')) # variables needed by do_one\n> ## \n> ## ## set up available via a call to available.packages() for\n> ## ## repositories containing all the packages involved and all their\n> ## ## dependencies.\n> ## DL <- utils:::.make_dependency_list(pkgs, available, recursive = TRUE)\n> ## DL <- lapply(DL, function(x) x[x %in% pkgs])\n> ## lens <- sapply(DL, length)\n> ## ready <- names(DL[lens == 0L])\n> ## done <- character() # packages already installed\n> ## n <- length(ready)\n> ## submit <- function(node, pkg)\n> ## parallel:::sendCall(cl[[node]], do_one, list(pkg), tag = pkg)\n> ## for (i in 1:min(n, M)) submit(i, ready[i])\n> ## DL <- DL[!names(DL) %in% ready[1:min(n, M)]]\n> ## av <- if(n < M) (n+1L):M else integer() # available workers\n> ## while(length(done) < length(pkgs)) {\n> ## d <- parallel:::recvOneResult(cl)\n> ## av <- c(av, d$node)\n> ## done <- c(done, d$tag)\n> ## OK <- unlist(lapply(DL, function(x) all(x %in% done) ))\n> ## if (!any(OK)) next\n> ## p <- names(DL)[OK]\n> ## m <- min(length(p), length(av)) # >= 1\n> ## for (i in 1:m) submit(av[i], p[i])\n> ## av <- av[-(1:m)]\n> ## DL <- DL[!names(DL) %in% p[1:m]]\n> ## }\n> \n> \n> ###################################################\n> ### code chunk number 14: parallel.Rnw:731-748 (eval = FALSE)\n> ###################################################\n> ## fn <- function(r) statistic(data, i[r, ], ...)\n> ## RR <- sum(R)\n> ## res <- if (ncpus > 1L && (have_mc || have_snow)) {\n> ## if (have_mc) {\n> ## parallel::mclapply(seq_len(RR), fn, mc.cores = ncpus)\n> ## } else if (have_snow) {\n> ## list(...) # evaluate any promises\n> ## if (is.null(cl)) {\n> ## cl <- parallel::makePSOCKcluster(rep(\'localhost\', ncpus))\n> ## if(RNGkind()[1L] == \'L\'Ecuyer-CMRG\')\n> ## parallel::clusterSetRNGStream(cl)\n> ## res <- parallel::parLapply(cl, seq_len(RR), fn)\n> ## parallel::stopCluster(cl)\n> ## res\n> ## } else parallel::parLapply(cl, seq_len(RR), fn)\n> ## }\n> ## } else lapply(seq_len(RR), fn)\n> \n> \n> ###################################################\n> ### code chunk number 15: parallel.Rnw:751-752 (eval = FALSE)\n> ###################################################\n> ## list(...) # evaluate any promises\n> \n> ', 1L, 150L); .Internal(substr(argv[[1]], argv[[2]], argv[[3]])) [1] "> ### R code from vignette source 'parallel.Rnw'\n> \n> ###################################################\n> ### code chunk number 1: parallel.Rnw:474-" +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', -1L, -1L, 'xyz') +[1] "xyzf" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', -1L, -2L, 'xyz') +[1] "xyzf" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', -1L, 0L, 'xyz') +[1] "ffff" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', -1L, 1L, 'xyz') +[1] "xfff" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', -1L, 2L, 'xyz') +[1] "xyff" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', -2L, -1L, 'xyz') +[1] "xyzf" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', -2L, -2L, 'xyz') +[1] "xyzf" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', -2L, 0L, 'xyz') +[1] "ffff" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', -2L, 1L, 'xyz') +[1] "xfff" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', -2L, 2L, 'xyz') +[1] "xyff" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', 0L, -1L, 'xyz') +[1] "xyzf" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', 0L, -2L, 'xyz') +[1] "xyzf" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', 0L, 0L, 'xyz') +[1] "ffff" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', 0L, 1L, 'xyz') +[1] "xfff" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', 0L, 2L, 'xyz') +[1] "xyff" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', 1L, -1L, 'xyz') +[1] "xyzf" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', 1L, -2L, 'xyz') +[1] "xyzf" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', 1L, 0L, 'xyz') +[1] "ffff" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', 1L, 1L, 'xyz') +[1] "xfff" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', 1L, 2L, 'xyz') +[1] "xyff" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', 2L, -1L, 'xyz') +[1] "fxyz" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', 2L, -2L, 'xyz') +[1] "fxyz" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', 2L, 0L, 'xyz') +[1] "ffff" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', 2L, 1L, 'xyz') +[1] "ffff" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`('ffff', 2L, 2L, 'xyz') +[1] "fxff" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), 2, 5, 1) +Error in `substr<-`(c("asdfasdf", "jfjfjf", "ffff"), 2, 5, 1) : + invalid value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), 2, 5, NULL) +Error in `substr<-`(c("asdfasdf", "jfjfjf", "ffff"), 2, 5, NULL) : + invalid value + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), 2, 5, c('a', 'asdf')) +[1] "aadfasdf" "jasdff" "faff" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), 2, c(5,15,-6), c('a', 'asdf')) +[1] "aadfasdf" "jasdff" "faff" + +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign# +#`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), c(1,10,-6), 5, c('a', 'asdf')) +[1] "asdfasdf" "jfjfjf" "afff" + ##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign1# #argv <- list('(0,5]', 1L, 1L, '['); .Internal(`substr<-`(argv[[1]], argv[[2]], argv[[3]], argv[[4]])) [1] "[0,5]" @@ -63598,11 +67893,11 @@ model.frame predict residuals [1] "a..ef" "q+++ty" "y..op[" "b" [5] "s..ff.blah.yech" -##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign_.testsubstrassign_1# +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign_1# #argv <- structure(list(x = c('NA', NA, 'BANANA'), start = 1, stop = 2, value = 'na'), .Names = c('x', 'start', 'stop', 'value'));do.call('substr<-', argv) [1] "na" NA "naNANA" -##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign_.testsubstrassign_2# +##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign_2# #argv <- structure(list(x = 'abcde', start = NA, stop = 3, value = 'abc'), .Names = c('x', 'start', 'stop', 'value'));do.call('substr<-', argv) [1] NA @@ -63686,20 +67981,24 @@ In sum(seq.int(-1, -1e+05)) : integer overflow - use sum(as.numeric(.)) Warning message: In sum(seq.int(1, 1e+05)) : integer overflow - use sum(as.numeric(.)) -##com.oracle.truffle.r.test.builtins.TestBuiltin_sum.testOveflow#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_sum.testOveflow# #sum(seq.int(from=-1, by=-1, length.out=100000)) [1] NA Warning message: In sum(seq.int(from = -1, by = -1, length.out = 1e+05)) : integer overflow - use sum(as.numeric(.)) -##com.oracle.truffle.r.test.builtins.TestBuiltin_sum.testOveflow#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.builtins.TestBuiltin_sum.testOveflow# #sum(seq.int(from=1, by=1, length.out=100000)) [1] NA Warning message: In sum(seq.int(from = 1, by = 1, length.out = 1e+05)) : integer overflow - use sum(as.numeric(.)) +##com.oracle.truffle.r.test.builtins.TestBuiltin_sum.testSum# +#sum(c(1,2,NA,3), na.rm=NA) +[1] 6 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_sum.testSum# #sum(v <- 42) [1] 42 @@ -63993,7 +68292,7 @@ Test for independence of all factors: Min. 1st Qu. Median Mean 3rd Qu. Max. 4.600 5.100 5.150 5.236 5.400 5.800 -##com.oracle.truffle.r.test.builtins.TestBuiltin_summary.testsummary3#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_summary.testsummary3# #argv <- structure(list(object = structure(list(Sepal.Length = c(5.1, 4.9, 4.7, 4.6, 5, 5.4, 4.6, 5, 4.4, 4.9, 5.4, 4.8, 4.8, 4.3, 5.8, 5.7, 5.4, 5.1, 5.7, 5.1, 5.4, 5.1, 4.6, 5.1, 4.8, 5, 5, 5.2, 5.2, 4.7, 4.8, 5.4, 5.2, 5.5, 4.9, 5, 5.5, 4.9, 4.4, 5.1, 5, 4.5, 4.4, 5, 5.1, 4.8, 5.1, 4.6, 5.3, 5, 7, 6.4, 6.9, 5.5, 6.5, 5.7, 6.3, 4.9, 6.6, 5.2, 5, 5.9, 6, 6.1, 5.6, 6.7, 5.6, 5.8, 6.2, 5.6, 5.9, 6.1, 6.3, 6.1, 6.4, 6.6, 6.8, 6.7, 6, 5.7, 5.5, 5.5, 5.8, 6, 5.4, 6, 6.7, 6.3, 5.6, 5.5, 5.5, 6.1, 5.8, 5, 5.6, 5.7, 5.7, 6.2, 5.1, 5.7, 6.3, 5.8, 7.1, 6.3, 6.5, 7.6, 4.9, 7.3, 6.7, 7.2, 6.5, 6.4, 6.8, 5.7, 5.8, 6.4, 6.5, 7.7, 7.7, 6, 6.9, 5.6, 7.7, 6.3, 6.7, 7.2, 6.2, 6.1, 6.4, 7.2, 7.4, 7.9, 6.4, 6.3, 6.1, 7.7, 6.3, 6.4, 6, 6.9, 6.7, 6.9, 5.8, 6.8, 6.7, 6.7, 6.3, 6.5, 6.2, 5.9), Sepal.Width = c(3.5, 3, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.4, 3, 3, 4, 4.4, 3.9, 3.5, 3.8, 3.8, 3.4, 3.7, 3.6, 3.3, 3.4, 3, 3.4, 3.5, 3.4, 3.2, 3.1, 3.4, 4.1, 4.2, 3.1, 3.2, 3.5, 3.6, 3, 3.4, 3.5, 2.3, 3.2, 3.5, 3.8, 3, 3.8, 3.2, 3.7, 3.3, 3.2, 3.2, 3.1, 2.3, 2.8, 2.8, 3.3, 2.4, 2.9, 2.7, 2, 3, 2.2, 2.9, 2.9, 3.1, 3, 2.7, 2.2, 2.5, 3.2, 2.8, 2.5, 2.8, 2.9, 3, 2.8, 3, 2.9, 2.6, 2.4, 2.4, 2.7, 2.7, 3, 3.4, 3.1, 2.3, 3, 2.5, 2.6, 3, 2.6, 2.3, 2.7, 3, 2.9, 2.9, 2.5, 2.8, 3.3, 2.7, 3, 2.9, 3, 3, 2.5, 2.9, 2.5, 3.6, 3.2, 2.7, 3, 2.5, 2.8, 3.2, 3, 3.8, 2.6, 2.2, 3.2, 2.8, 2.8, 2.7, 3.3, 3.2, 2.8, 3, 2.8, 3, 2.8, 3.8, 2.8, 2.8, 2.6, 3, 3.4, 3.1, 3, 3.1, 3.1, 3.1, 2.7, 3.2, 3.3, 3, 2.5, 3, 3.4, 3), Petal.Length = c(1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.6, 1.4, 1.1, 1.2, 1.5, 1.3, 1.4, 1.7, 1.5, 1.7, 1.5, 1, 1.7, 1.9, 1.6, 1.6, 1.5, 1.4, 1.6, 1.6, 1.5, 1.5, 1.4, 1.5, 1.2, 1.3, 1.4, 1.3, 1.5, 1.3, 1.3, 1.3, 1.6, 1.9, 1.4, 1.6, 1.4, 1.5, 1.4, 4.7, 4.5, 4.9, 4, 4.6, 4.5, 4.7, 3.3, 4.6, 3.9, 3.5, 4.2, 4, 4.7, 3.6, 4.4, 4.5, 4.1, 4.5, 3.9, 4.8, 4, 4.9, 4.7, 4.3, 4.4, 4.8, 5, 4.5, 3.5, 3.8, 3.7, 3.9, 5.1, 4.5, 4.5, 4.7, 4.4, 4.1, 4, 4.4, 4.6, 4, 3.3, 4.2, 4.2, 4.2, 4.3, 3, 4.1, 6, 5.1, 5.9, 5.6, 5.8, 6.6, 4.5, 6.3, 5.8, 6.1, 5.1, 5.3, 5.5, 5, 5.1, 5.3, 5.5, 6.7, 6.9, 5, 5.7, 4.9, 6.7, 4.9, 5.7, 6, 4.8, 4.9, 5.6, 5.8, 6.1, 6.4, 5.6, 5.1, 5.6, 6.1, 5.6, 5.5, 4.8, 5.4, 5.6, 5.1, 5.1, 5.9, 5.7, 5.2, 5, 5.2, 5.4, 5.1), Petal.Width = c(0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.2, 0.1, 0.1, 0.2, 0.4, 0.4, 0.3, 0.3, 0.3, 0.2, 0.4, 0.2, 0.5, 0.2, 0.2, 0.4, 0.2, 0.2, 0.2, 0.2, 0.4, 0.1, 0.2, 0.2, 0.2, 0.2, 0.1, 0.2, 0.2, 0.3, 0.3, 0.2, 0.6, 0.4, 0.3, 0.2, 0.2, 0.2, 0.2, 1.4, 1.5, 1.5, 1.3, 1.5, 1.3, 1.6, 1, 1.3, 1.4, 1, 1.5, 1, 1.4, 1.3, 1.4, 1.5, 1, 1.5, 1.1, 1.8, 1.3, 1.5, 1.2, 1.3, 1.4, 1.4, 1.7, 1.5, 1, 1.1, 1, 1.2, 1.6, 1.5, 1.6, 1.5, 1.3, 1.3, 1.3, 1.2, 1.4, 1.2, 1, 1.3, 1.2, 1.3, 1.3, 1.1, 1.3, 2.5, 1.9, 2.1, 1.8, 2.2, 2.1, 1.7, 1.8, 1.8, 2.5, 2, 1.9, 2.1, 2, 2.4, 2.3, 1.8, 2.2, 2.3, 1.5, 2.3, 2, 2, 1.8, 2.1, 1.8, 1.8, 1.8, 2.1, 1.6, 1.9, 2, 2.2, 1.5, 1.4, 2.3, 2.4, 1.8, 1.8, 2.1, 2.4, 2.3, 1.9, 2.3, 2.5, 2.3, 1.9, 2, 2.3, 1.8), Species = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c('setosa', 'versicolor', 'virginica'), class = 'factor')), .Names = c('Sepal.Length', 'Sepal.Width', 'Petal.Length', 'Petal.Width', 'Species'), row.names = c(NA, -150L), class = 'data.frame')), .Names = 'object');do.call('summary', argv) Sepal.Length Sepal.Width Petal.Length Petal.Width Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100 @@ -64183,6 +68482,31 @@ Error: duplicate 'switch' defaults: 'v77' and 'v55' ##com.oracle.truffle.r.test.builtins.TestBuiltin_switch.testSwitch# #{switch(4,1,2,z)} +##com.oracle.truffle.r.test.builtins.TestBuiltin_switch.testSwitchInvalidExpr# +#{ switch(quote(a), 1, 2, 3) } +Error in switch(quote(a), 1, 2, 3) : EXPR must be a length 1 vector + +##com.oracle.truffle.r.test.builtins.TestBuiltin_switch.testSwitchInvalidExpr# +#{ x <- switch(NA, 1, 2, 3); x } +NULL + +##com.oracle.truffle.r.test.builtins.TestBuiltin_switch.testSwitchInvalidExpr# +#{ x <- switch(expression(quote(1)), 1, 2, 3); x } +NULL + +##com.oracle.truffle.r.test.builtins.TestBuiltin_switch.testSwitchInvalidExpr# +#{ x <- switch(expression(quote(1), quote(2)), 1, 2, 3); x } +Error in switch(expression(quote(1), quote(2)), 1, 2, 3) : + EXPR must be a length 1 vector + +##com.oracle.truffle.r.test.builtins.TestBuiltin_switch.testSwitchInvalidExpr# +#{ x <- switch(list(1,2,3), 1, 2, 3); x } +Error in switch(list(1, 2, 3), 1, 2, 3) : EXPR must be a length 1 vector + +##com.oracle.truffle.r.test.builtins.TestBuiltin_switch.testSwitchInvalidExpr# +#{ x <- switch(list(2), 1, 2, 3); x } +NULL + ##com.oracle.truffle.r.test.builtins.TestBuiltin_switch.testswitch1# #argv <- structure(list('forward', forward = 'posS', reverse = 'negS'), .Names = c('', 'forward', 'reverse'));do.call('switch', argv) [1] "posS" @@ -65112,7 +69436,7 @@ attr(,"assign") object [1,] "foo" -##com.oracle.truffle.r.test.builtins.TestBuiltin_tdefault.testtdefault13#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_tdefault.testtdefault13# #argv <- list(structure(c(0, 0, 0, 0, 0, 0, 3.95252516672997e-323, 0, 0, 0, 0, 0), .Dim = c(12L, 1L))); .Internal(t.default(argv[[1]])) [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [1,] 0 0 0 0 0 0 3.952525e-323 0 0 0 0 0 @@ -65694,6 +70018,10 @@ tracemem[0x7f878bbeec90 -> 0x7f878bbeeb28]: tracemem[<0x7faf1a058090> -> 0x7faf191a98a8]: tracemem[0x7faf191a98a8 -> 0x7faf191a98e0]: +##com.oracle.truffle.r.test.builtins.TestBuiltin_tracemem.retracemem#Output.ContainsReferences# +#x<-1:10; retracemem(x, c("first", "second")) +tracemem[first -> 0x1d805c0]: + ##com.oracle.truffle.r.test.builtins.TestBuiltin_tracemem.vectors#Output.ContainsReferences# #v <- c(1,10,100); tracemem(v); x <- v; y <- v; x[[1]]<-42; untracemem(v); y[[2]] <- 84 [1] "<0x7ff2cd448c90>" @@ -67407,7 +71735,7 @@ attr(,"Rd_tag") #argv <- list(list(c(13823, NA)), TRUE, TRUE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]])) [1] 13823 NA -##com.oracle.truffle.r.test.builtins.TestBuiltin_unlist.testunlist20#Ignored.Unknown# +##com.oracle.truffle.r.test.builtins.TestBuiltin_unlist.testunlist20# #argv <- list(structure(list(`1` = 2.47032822920623e-323), .Names = '1'), FALSE, TRUE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]])) 1 2.470328e-323 @@ -67551,8 +71879,8 @@ $c [1] NA -##com.oracle.truffle.r.test.builtins.TestBuiltin_unlist.testunlist27#Ignored.Unknown# -#argv <- list(list(structure(list(structure(c(0.398105880367068, -0.612026393250771, 0.341119691424425, -1.12936309608079, 1.43302370170104, 1.98039989850586, -0.367221476466509, -1.04413462631653, 0.569719627442413, -0.135054603880824, 2.40161776050478, -0.0392400027331692, 0.689739362450777, 0.0280021587806661, -0.743273208882405, 0.188792299514343, -1.80495862889104, 1.46555486156289, 0.153253338211898, 2.17261167036215, 0.475509528899663, -0.709946430921815, 0.610726353489055, -0.934097631644252, -1.2536334002391, 0.291446235517463, -0.443291873218433, 0.00110535163162413, 0.0743413241516641, -0.589520946188072, -0.568668732818502, -0.135178615123832, 1.1780869965732, -1.52356680042976, 0.593946187628422, 0.332950371213518, 1.06309983727636, -0.304183923634301, 0.370018809916288, 0.267098790772231, -0.54252003099165, 1.20786780598317, 1.16040261569495, 0.700213649514998, 1.58683345454085, 0.558486425565304, -1.27659220845804, -0.573265414236886, -1.22461261489836, -0.473400636439312, -0.620366677224124, 0.0421158731442352, -0.910921648552446, 0.158028772404075, -0.654584643918818, 1.76728726937265, 0.716707476017206, 0.910174229495227, 0.384185357826345, 1.68217608051942, -0.635736453948977, -0.461644730360566, 1.43228223854166, -0.650696353310367, -0.207380743601965, -0.392807929441984, -0.319992868548507, -0.279113302976559, 0.494188331267827, -0.177330482269606, -0.505957462114257, 1.34303882517041, -0.214579408546869, -0.179556530043387, -0.100190741213562, 0.712666307051405, -0.0735644041263263, -0.0376341714670479, -0.681660478755657, -0.324270272246319, 0.0601604404345152, -0.588894486259664, 0.531496192632572, -1.51839408178679, 0.306557860789766, -1.53644982353759, -0.300976126836611, -0.528279904445006, -0.652094780680999, -0.0568967778473925, -1.91435942568001, 1.17658331201856, -1.664972436212, -0.463530401472386, -1.11592010504285, -0.750819001193448, 2.08716654562835, 0.0173956196932517, -1.28630053043433, -1.64060553441858), .Label = structure(list(c(-1.91442143130152, -0.573203408615382), c(-0.934159637265755, -0.300914121215107), c(-0.568730738440006, 0.0174576253147555), c(-0.279175308598063, 0.384247363447848), c(0.0279401531591622, 1.16046462131646), c(0.398043874745564, 2.40167976612628)), class = 'shingleLevel'), class = 'shingle')), row.names = c(NA, -100L), class = 'data.frame'), structure(list(c(0.450187101272656, -0.018559832714638, -0.318068374543844, -0.929362147453702, -1.48746031014148, -1.07519229661568, 1.00002880371391, -0.621266694796823, -1.38442684738449, 1.86929062242358, 0.425100377372448, -0.238647100913033, 1.05848304870902, 0.886422651374936, -0.619243048231147, 2.20610246454047, -0.255027030141015, -1.42449465021281, -0.144399601954219, 0.207538339232345, 2.30797839905936, 0.105802367893711, 0.456998805423414, -0.077152935356531, -0.334000842366544, -0.0347260283112762, 0.787639605630162, 2.07524500865228, 1.02739243876377, 1.2079083983867, -1.23132342155804, 0.983895570053379, 0.219924803660651, -1.46725002909224, 0.521022742648139, -0.158754604716016, 1.4645873119698, -0.766081999604665, -0.430211753928547, -0.926109497377437, -0.17710396143654, 0.402011779486338, -0.731748173119606, 0.830373167981674, -1.20808278630446, -1.04798441280774, 1.44115770684428, -1.01584746530465, 0.411974712317515, -0.38107605110892, 0.409401839650934, 1.68887328620405, 1.58658843344197, -0.330907800682766, -2.28523553529247, 2.49766158983416, 0.667066166765493, 0.5413273359637, -0.0133995231459087, 0.510108422952926, -0.164375831769667, 0.420694643254513, -0.400246743977644, -1.37020787754746, 0.987838267454879, 1.51974502549955, -0.308740569225614, -1.25328975560769, 0.642241305677824, -0.0447091368939791, -1.73321840682484, 0.00213185968026965, -0.630300333928146, -0.340968579860405, -1.15657236263585, 1.80314190791747, -0.331132036391221, -1.60551341225308, 0.197193438739481, 0.263175646405474, -0.985826700409291, -2.88892067167955, -0.640481702565115, 0.570507635920485, -0.05972327604261, -0.0981787440052344, 0.560820728620116, -1.18645863857947, 1.09677704427424, -0.00534402827816569, 0.707310667398079, 1.03410773473746, 0.223480414915304, -0.878707612866019, 1.16296455596733, -2.00016494478548, -0.544790740001725, -0.255670709156989, -0.166121036765006, 1.02046390878411)), row.names = c(NA, -100L), class = 'data.frame')), FALSE, FALSE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]])) +##com.oracle.truffle.r.test.builtins.TestBuiltin_unlist.testunlist27#Output.IgnoreWhitespace# +#argv <- list(list(structure(list(structure(c(0.398105880367068, -0.612026393250771, 0.341119691424425, -1.12936309608079, 1.43302370170104, 1.98039989850586, -0.367221476466509, -1.04413462631653, 0.569719627442413, -0.135054603880824, 2.40161776050478, -0.0392400027331692, 0.689739362450777, 0.0280021587806661, -0.743273208882405, 0.188792299514343, -1.80495862889104, 1.46555486156289, 0.153253338211898, 2.17261167036215, 0.475509528899663, -0.709946430921815, 0.610726353489055, -0.934097631644252, -1.2536334002391, 0.291446235517463, -0.443291873218433, 0.00110535163162413, 0.0743413241516641, -0.589520946188072, -0.568668732818502, -0.135178615123832, 1.1780869965732, -1.52356680042976, 0.593946187628422, 0.332950371213518, 1.06309983727636, -0.304183923634301, 0.370018809916288, 0.267098790772231, -0.54252003099165, 1.20786780598317, 1.16040261569495, 0.700213649514998, 1.58683345454085, 0.558486425565304, -1.27659220845804, -0.573265414236886, -1.22461261489836, -0.473400636439312, -0.620366677224124, 0.0421158731442352, -0.910921648552446, 0.158028772404075, -0.654584643918818, 1.76728726937265, 0.716707476017206, 0.910174229495227, 0.384185357826345, 1.68217608051942, -0.635736453948977, -0.461644730360566, 1.43228223854166, -0.650696353310367, -0.207380743601965, -0.392807929441984, -0.319992868548507, -0.279113302976559, 0.494188331267827, -0.177330482269606, -0.505957462114257, 1.34303882517041, -0.214579408546869, -0.179556530043387, -0.100190741213562, 0.712666307051405, -0.0735644041263263, -0.0376341714670479, -0.681660478755657, -0.324270272246319, 0.0601604404345152, -0.588894486259664, 0.531496192632572, -1.51839408178679, 0.306557860789766, -1.53644982353759, -0.300976126836611, -0.528279904445006, -0.652094780680999, -0.0568967778473925, -1.91435942568001, 1.17658331201856, -1.664972436212, -0.463530401472386, -1.11592010504285, -0.750819001193448, 2.08716654562835, 0.0173956196932517, -1.28630053043433, -1.64060553441858), .Label = structure(list(c(-1.91442143130152, -0.573203408615382), c(-0.934159637265755, -0.300914121215107), c(-0.568730738440006, 0.0174576253147555), c(-0.279175308598063, 0.384247363447848), c(0.0279401531591622, 1.16046462131646), c(0.398043874745564, 2.40167976612628)), class = 'shingleLevel'), class = 'shingle')), row.names = c(NA, -100L), class = 'data.frame'), structure(list(c(0.450187101272656, -0.018559832714638, -0.318068374543844, -0.929362147453702, -1.48746031014148, -1.07519229661568, 1.00002880371391, -0.621266694796823, -1.38442684738449, 1.86929062242358, 0.425100377372448, -0.238647100913033, 1.05848304870902, 0.886422651374936, -0.619243048231147, 2.20610246454047, -0.255027030141015, -1.42449465021281, -0.144399601954219, 0.207538339232345, 2.30797839905936, 0.105802367893711, 0.456998805423414, -0.077152935356531, -0.334000842366544, -0.0347260283112762, 0.787639605630162, 2.07524500865228, 1.02739243876377, 1.2079083983867, -1.23132342155804, 0.983895570053379, 0.219924803660651, -1.46725002909224, 0.521022742648139, -0.158754604716016, 1.4645873119698, -0.766081999604665, -0.430211753928547, -0.926109497377437, -0.17710396143654, 0.402011779486338, -0.731748173119606, 0.830373167981674, -1.20808278630446, -1.04798441280774, 1.44115770684428, -1.01584746530465, 0.411974712317515, -0.38107605110892, 0.409401839650934, 1.68887328620405, 1.58658843344197, -0.330907800682766, -2.28523553529247, 2.49766158983416, 0.667066166765493, 0.5413273359637, -0.0133995231459087, 0.510108422952926, -0.164375831769667, 0.420694643254513, -0.400246743977644, -1.37020787754746, 0.987838267454879, 1.51974502549955, -0.308740569225614, -1.25328975560769, 0.642241305677824, -0.0447091368939791, -1.73321840682484, 0.00213185968026965, -0.630300333928146, -0.340968579860405, -1.15657236263585, 1.80314190791747, -0.331132036391221, -1.60551341225308, 0.197193438739481, 0.263175646405474)), row.names = c(NA, -80L), class = 'data.frame')), FALSE, FALSE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]])) [[1]] [1] 0.398105880 -0.612026393 0.341119691 -1.129363096 1.433023702 [6] 1.980399899 -0.367221476 -1.044134626 0.569719627 -0.135054604 @@ -67599,26 +71927,20 @@ attr(,"class") [1] "shingle" [[2]] - [1] 0.450187101 -0.018559833 -0.318068375 -0.929362147 -1.487460310 - [6] -1.075192297 1.000028804 -0.621266695 -1.384426847 1.869290622 - [11] 0.425100377 -0.238647101 1.058483049 0.886422651 -0.619243048 - [16] 2.206102465 -0.255027030 -1.424494650 -0.144399602 0.207538339 - [21] 2.307978399 0.105802368 0.456998805 -0.077152935 -0.334000842 - [26] -0.034726028 0.787639606 2.075245009 1.027392439 1.207908398 - [31] -1.231323422 0.983895570 0.219924804 -1.467250029 0.521022743 - [36] -0.158754605 1.464587312 -0.766082000 -0.430211754 -0.926109497 - [41] -0.177103961 0.402011779 -0.731748173 0.830373168 -1.208082786 - [46] -1.047984413 1.441157707 -1.015847465 0.411974712 -0.381076051 - [51] 0.409401840 1.688873286 1.586588433 -0.330907801 -2.285235535 - [56] 2.497661590 0.667066167 0.541327336 -0.013399523 0.510108423 - [61] -0.164375832 0.420694643 -0.400246744 -1.370207878 0.987838267 - [66] 1.519745025 -0.308740569 -1.253289756 0.642241306 -0.044709137 - [71] -1.733218407 0.002131860 -0.630300334 -0.340968580 -1.156572363 - [76] 1.803141908 -0.331132036 -1.605513412 0.197193439 0.263175646 - [81] -0.985826700 -2.888920672 -0.640481703 0.570507636 -0.059723276 - [86] -0.098178744 0.560820729 -1.186458639 1.096777044 -0.005344028 - [91] 0.707310667 1.034107735 0.223480415 -0.878707613 1.162964556 - [96] -2.000164945 -0.544790740 -0.255670709 -0.166121037 1.020463909 + [1] 0.45018710 -0.01855983 -0.31806837 -0.92936215 -1.48746031 -1.07519230 + [7] 1.00002880 -0.62126669 -1.38442685 1.86929062 0.42510038 -0.23864710 +[13] 1.05848305 0.88642265 -0.61924305 2.20610246 -0.25502703 -1.42449465 +[19] -0.14439960 0.20753834 2.30797840 0.10580237 0.45699881 -0.07715294 +[25] -0.33400084 -0.03472603 0.78763961 2.07524501 1.02739244 1.20790840 +[31] -1.23132342 0.98389557 0.21992480 -1.46725003 0.52102274 -0.15875460 +[37] 1.46458731 -0.76608200 -0.43021175 -0.92610950 -0.17710396 0.40201178 +[43] -0.73174817 0.83037317 -1.20808279 -1.04798441 1.44115771 -1.01584747 +[49] 0.41197471 -0.38107605 0.40940184 1.68887329 1.58658843 -0.33090780 +[55] -2.28523554 2.49766159 0.66706617 0.54132734 -0.01339952 0.51010842 +[61] -0.16437583 0.42069464 -0.40024674 -1.37020788 0.98783827 1.51974503 +[67] -0.30874057 -1.25328976 0.64224131 -0.04470914 -1.73321841 0.00213186 +[73] -0.63030033 -0.34096858 -1.15657236 1.80314191 -0.33113204 -1.60551341 +[79] 0.19719344 0.26317565 ##com.oracle.truffle.r.test.builtins.TestBuiltin_unlist.testunlist28# @@ -68003,6 +72325,14 @@ numeric(0) #unserialize(serialize("Hello world", NULL)) [1] "Hello world" +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.tests# +#unserialize(serialize((1:15)+0.1, NULL)) + [1] 1.1 2.1 3.1 4.1 5.1 6.1 7.1 8.1 9.1 10.1 11.1 12.1 13.1 14.1 15.1 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.tests# +#unserialize(serialize(1:15, NULL)) + [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.tests# #unserialize(serialize(3+2i, NULL)) [1] 3+2i @@ -68027,6 +72357,18 @@ NULL #unserialize(serialize(c(1,2,3,4), NULL)) [1] 1 2 3 4 +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.tests# +#unserialize(serialize(c(1L,2L,99L,NA), NULL)) +[1] 1 2 99 NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.tests# +#unserialize(serialize(c(3+2i, 5+944i, NA), NULL)) +[1] 3+ 2i 5+944i NA + +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.tests# +#unserialize(serialize(c(TRUE, FALSE, NA, FALSE, TRUE), NULL)) +[1] TRUE FALSE NA FALSE TRUE + ##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.tests# #unserialize(serialize(data.frame(col1=c(9,8,7), col2=1:3), NULL)) col1 col2 @@ -68190,7 +72532,7 @@ function(x, y = 1, ...) { NA } -##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Ignored.OutputFormatting# +##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize# #options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y,...) { !!NA }), connection=NULL)) function(x = { 1 + a @@ -68444,6 +72786,10 @@ Error in vapply(c("foo", "bar"), function(x) FALSE, function() 42) : #{ vapply(c("hello", "goodbye", "up", "down"), function(x) x, c("a"), USE.NAMES = FALSE) } [1] "hello" "goodbye" "up" "down" +##com.oracle.truffle.r.test.builtins.TestBuiltin_vapply.testVapply# +#{ vapply(c(1,2,3), 42, 1); } +Error in match.fun(FUN) : '42' is not a function, character or symbol + ##com.oracle.truffle.r.test.builtins.TestBuiltin_vapply.testVapply# #{ vapply(c(10, 20, 30, 40), function(x) x/2, c(1)) } [1] 5 10 15 20 @@ -68468,6 +72814,15 @@ Error in vapply(c("foo", "bar"), function(x) FALSE, function() 42) : #{ vapply(c(TRUE, FALSE, TRUE), function(x) x, c(TRUE)) } [1] TRUE FALSE TRUE +##com.oracle.truffle.r.test.builtins.TestBuiltin_vapply.testVapply# +#{ vapply(quote(a), function(x) 42, 1); } +[1] 42 + +##com.oracle.truffle.r.test.builtins.TestBuiltin_vapply.testVapply#Output.IgnoreErrorContext# +#{ vapply(quote(a), function(x) quote(b), quote(a)); } +Error in vapply(quote(a), function(x) quote(b), quote(a)) : + 'FUN.VALUE' must be a vector + ##com.oracle.truffle.r.test.builtins.TestBuiltin_vector.testVectorConstructor# #{ vector("numeric", c(7, 42)) } Error in vector("numeric", c(7, 42)) : invalid 'length' argument @@ -68852,6 +73207,18 @@ $visible #argv <- structure(list(data = structure(list(a = 1:5, b = 2:6, c = 3:7), .Names = c('a', 'b', 'c'), row.names = c(NA, -5L), class = 'data.frame')), .Names = 'data');do.call('within', argv) Error in eval(expr, envir, enclos) : argument is missing, with no default +##com.oracle.truffle.r.test.builtins.TestBuiltin_writeChar.testwriteCharArgumentsValidation# +#writeChar(42, 1) +Error in writeChar(42, 1) : can only write character objects + +##com.oracle.truffle.r.test.builtins.TestBuiltin_writeChar.testwriteCharArgumentsValidation# +#writeChar(NULL, 1) +Error in writeChar(NULL, 1) : can only write character objects + +##com.oracle.truffle.r.test.builtins.TestBuiltin_writeChar.testwriteCharArgumentsValidation# +#writeChar(list(), 1) +Error in writeChar(list(), 1) : can only write character objects + ##com.oracle.truffle.r.test.builtins.TestBuiltin_writeLines.testwriteLines1#Ignored.SideEffects# #argv <- structure(list(text = ' \' A \'; \'B\' ;\'C\';\' D \';\'E \'; F ;G ', con = 'foo'), .Names = c('text', 'con'));do.call('writeLines', argv) @@ -71627,11 +75994,11 @@ Warning message: In foo(42) : IgnoreWarningContext [1] 42 -##com.oracle.truffle.r.test.functions.TestFunctions.testDefaultArgs#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.functions.TestFunctions.testDefaultArgs# #{ array(dim=c(-2,-2)); } Error in array(dim = c(-2, -2)) : the dims contain negative values -##com.oracle.truffle.r.test.functions.TestFunctions.testDefaultArgs#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.functions.TestFunctions.testDefaultArgs# #{ array(dim=c(-2,2)); } Error in array(dim = c(-2, 2)) : negative length vectors are not allowed @@ -72015,6 +76382,10 @@ Error in f(10) : ..1 used in an incorrect context, no ... to look in [1] FALSE [1] "bar" +##com.oracle.truffle.r.test.functions.TestFunctions.testDots# +#{ f1 <- function(...) { subst <- substitute(list(...))[-1L]; eval(subst[[1]]) }; f2 <- function(a, ...) TRUE; f3 <- function(a, ...) { cat("Here:"); f1(f2(a, ...)) }; f1(f3("aaa")) } +Here:[1] TRUE + ##com.oracle.truffle.r.test.functions.TestFunctions.testDots# #{ f<-function(...) print(attributes(list(...))); f(a=7) } $names @@ -72250,6 +76621,10 @@ function(x) x #{ sum } function (..., na.rm = FALSE) .Primitive("sum") +##com.oracle.truffle.r.test.functions.TestFunctions.testFunctionResultPrinting# +#{ foo <- function() { x <- 1; return(x) }; foo() } +[1] 1 + ##com.oracle.truffle.r.test.functions.TestFunctions.testInvocation# #{ f <- function(...) { args <- list(...) ; args$name } ; f(name = 42) } [1] 42 @@ -73180,9 +77555,49 @@ f first 1 ##com.oracle.truffle.r.test.library.base.TestConditionHandling.runRSourceTests# #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers0.R") } +{ + fun1("first") + fun1("second") +} +[1] "enter fun1 first" +[1] "enter handle_myCondition myCondition: signalfirst\n" +[1] "continue" +[1] "exit fun1 first" +[1] "enter fun1 second" +[1] "enter handle_myCondition myCondition: signalsecond\n" +[1] "continue" +[1] "exit fun1 second" +[1] "exit fun0" +[1] "enter fun1 first" +[1] "enter handle_myCondition myCondition: signalfirst\n" +[1] "continue" +[1] "exit fun1 first" +[1] "enter fun1 second" +[1] "enter handle_myCondition myCondition: signalsecond\n" +[1] "continue" +[1] "exit fun1 second" +NULL +[1] "exit fun0" -##com.oracle.truffle.r.test.library.base.TestConditionHandling.runRSourceTests#Ignored.Unknown# +##com.oracle.truffle.r.test.library.base.TestConditionHandling.runRSourceTests# #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers1.R") } +{ + fun1("first") + fun1("second") +} +[1] "enter fun1 first" +[1] "enter handle_cond1 cond1: signalfirst\n" +[1] "after cond1 restart" +[1] "enter handle_cond0 cond0: signalfirst\n" +[1] "continue" +[1] "exit fun1 first" +[1] "enter fun1 second" +[1] "enter handle_cond1 cond1: signalsecond\n" +[1] "after cond1 restart" +[1] "enter handle_cond0 cond0: signalsecond\n" +[1] "continue" +[1] "exit fun1 second" +[1] "exit fun0" [1] "enter fun1 first" [1] "enter handle_cond1 cond1: signalfirst\n" [1] "after cond1 restart" @@ -73198,10 +77613,6 @@ f first 1 NULL [1] "exit fun0" -##com.oracle.truffle.r.test.library.base.TestConditionHandling.testTryCatch# -#myCondition <- function(message, call=NULL)<<<NEWLINE>>> structure(list(message=message, call=call),<<<NEWLINE>>> class=c("myCondition", "condition"))<<<NEWLINE>>>tryCatch(signalCondition(myCondition("foo")),<<<NEWLINE>>> myCondition=function(cond) {cat("<my>");123L}) -<my>[1] 123 - ##com.oracle.truffle.r.test.library.base.TestConditionHandling.testTryCatch# #{ e <- simpleError("test error"); f <- function() { tryCatch(1, finally = print("Hello")); stop(e)}; f() } [1] "Hello" @@ -73244,6 +77655,16 @@ Error in tryCatchList(expr, classes, parentenv, handlers) : fred #{ tryCatch(stop("xyz"), error=function(e) { cat("<error>");123L }, finally=function() { cat("<finally>")}) } <error>[1] 123 +##com.oracle.truffle.r.test.library.base.TestConditionHandling.testWithCallingHandlers#Output.IgnoreErrorContext# +#withCallingHandlers(stop('error message'), error=function(e) {}) +Error in withCallingHandlers(stop("error message"), error = function(e) { : + error message + +##com.oracle.truffle.r.test.library.base.TestConditionHandling.testWithCallingHandlers#Output.IgnoreErrorMessage# +#withCallingHandlers(unknownSymbol(), condition = function(e) {}) +Error in withCallingHandlers(unknownSymbol(), condition = function(e) { : + could not find function "unknownSymbol" + ##com.oracle.truffle.r.test.library.base.TestConditionHandling.testWithCallingHandlers# #withCallingHandlers({message("foo");123L},<<<NEWLINE>>> message=function(e) {<<<NEWLINE>>> cat("<msg>")<<<NEWLINE>>> invokeRestart("muffleMessage")<<<NEWLINE>>> }) <msg>[1] 123 @@ -73297,6 +77718,120 @@ NULL #withRestarts({cat("<start>");invokeRestart("foo", 123L, 456L);789L},<<<NEWLINE>>> foo=list(description="my handler", handler=function(a,b) c(a,b))) <start>[1] 123 456 +##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests#Ignored.Unknown# +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/fifo_GnuR_example.R") } +[1] "abc" + +##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests# +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readBin.R") } + +##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests# +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readWriteBin.R") } + +##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests# +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_seek.R") } + +##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests# +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_writeBin.R") } + +##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests# +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R") } +[1] "TITLE extra line" "2 3 5 7" "" "11 13 17" +[5] "123" "abc" "123" "abc def" +Warning message: +In readLines("test1") : incomplete final line found on 'test1' + +##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests# +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/textConnection.R") } +Read 4 items +Read 4 items + +Summary of Residuals: + + +##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding# +#fin <- file('', "w+", encoding = "___inexistingCharSet___") +Error in file("", "w+", encoding = "___inexistingCharSet___") : + unsupported conversion from '___inexistingCharSet___' to '' + +##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding# +#{ wline <- 'Hellö'; fin <- file('', 'w+', encoding = 'UTF-8'); writeLines(wline, fin); seek(fin, 0); rline <- readLines(fin, 1); close(fin); c(wline, rline, wline == rline) } +[1] "Hellö" "Hellö" "TRUE" + +##com.oracle.truffle.r.test.library.base.TestConnections.testFifoOpenInexisting# +#capabilities("fifo") +fifo +TRUE + +##com.oracle.truffle.r.test.library.base.TestConnections.testFifoOpenInexisting# +#{ fn <- '___fifo_2367253765'; zz <- fifo(fn, 'r', blocking = TRUE); close(zz); unlink(fn) } +Error in fifo(fn, "r", blocking = TRUE) : cannot open the connection +In addition: Warning message: +In fifo(fn, "r", blocking = TRUE) : cannot open fifo '___fifo_2367253765' + +##com.oracle.truffle.r.test.library.base.TestConnections.testFileOpenRaw# +#{ zz <- file("gzipped_____5137528280012599068___.gz", "r", raw=T); res <- readBin(zz, raw(), 4); close(zz); res } +Error in readBin(zz, raw(), 4) : can only read from a binary connection + +##com.oracle.truffle.r.test.library.base.TestConnections.testFileOpenRaw# +#{ zz <- rawConnection(as.raw(c(65, 66, 67, 0, 97, 98, 99))); readChar(zz, 6) } +[1] "ABC" + +##com.oracle.truffle.r.test.library.base.TestConnections.testFileSummary# +#zz <- file('', 'w+'); summary(zz); close(zz) +$description +[1] "" + +$class +[1] "file" + +$mode +[1] "w+" + +$text +[1] "text" + +$opened +[1] "opened" + +$`can read` +[1] "yes" + +$`can write` +[1] "yes" + + +##com.oracle.truffle.r.test.library.base.TestConnections.testFileSummary# +#{ zz <- file("gzipped_____5137528280012599068___.gz", "r"); res <- summary(zz); close(zz); res } +$description +[1] "gzipped_____5137528280012599068___.gz" + +$class +[1] "gzfile" + +$mode +[1] "r" + +$text +[1] "text" + +$opened +[1] "opened" + +$`can read` +[1] "yes" + +$`can write` +[1] "no" + + +##com.oracle.truffle.r.test.library.base.TestConnections.testFileWriteReadBin# +#{ cat('abc', file = 'tmptest/com.oracle.truffle.r.test.library.base.conn/wb3'); readBin(file('tmptest/com.oracle.truffle.r.test.library.base.conn/wb3', 'rb'), character(), 2) } +character(0) +Warning message: +In readBin(file("tmptest/com.oracle.truffle.r.test.library.base.conn/wb3", : + incomplete string at end of file has been discarded + ##com.oracle.truffle.r.test.library.base.TestConnections.testFileWriteReadBin# #{ readBin(file("tmptest/com.oracle.truffle.r.test.library.base.conn/wb1", "rb"), 3) } numeric(0) @@ -73304,6 +77839,10 @@ numeric(0) ##com.oracle.truffle.r.test.library.base.TestConnections.testFileWriteReadBin# #{ writeBin("abc", file("tmptest/com.oracle.truffle.r.test.library.base.conn/wb1", open="wb")) } +##com.oracle.truffle.r.test.library.base.TestConnections.testFileWriteReadBin# +#{ zz <- file("tmptest/com.oracle.truffle.r.test.library.base.conn/wb2", open="wb"); writeChar("abc", zz); close(zz); readBin(file("tmptest/com.oracle.truffle.r.test.library.base.conn/wb2", "rb"), character(), 4) } +[1] "abc" + ##com.oracle.truffle.r.test.library.base.TestConnections.testFileWriteReadChar# #{ readChar(file("tmptest/com.oracle.truffle.r.test.library.base.conn/wc1"), 3) } [1] "abc" @@ -73401,6 +77940,278 @@ numeric(0) #{ con<-textConnection(c("a","b","c","d")); pushBackLength(con) } [1] 0 +##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadAppendText# +#{ rc <- rawConnection(raw(0), "a+"); close(rc); write(charToRaw("A"), rc) } +Error in cat(x, file = file, sep = c(rep.int(sep, ncolumns - 1), "\n"), : + invalid connection + +##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadAppendText# +#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "a+"); write(charToRaw(", World"), rc); res <- rawConnectionValue(rc); close(rc); res } + [1] 48 65 6c 6c 6f 32 63 20 32 30 20 35 37 20 36 66 20 37 32 0a 36 63 20 36 34 +[26] 0a + +##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadAppendText# +#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "a+"); write(charToRaw(", World"), rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res } +[1] "Hello2c 20 57 6f 72\n6c 64\n" + +##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadAppendText# +#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "a+"); writeChar(", World", rc); res <- rawConnectionValue(rc); close(rc); res } + [1] 48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 00 + +##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadAppendText# +#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "a+"); writeChar(", World", rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res } +[1] "Hello, World" + +##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadWriteText# +#{ rc <- rawConnection(raw(0), "r+"); close(rc); write(charToRaw("A"), rc) } +Error in cat(x, file = file, sep = c(rep.int(sep, ncolumns - 1), "\n"), : + invalid connection + +##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadWriteText# +#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "r+"); write(charToRaw(", World"), rc); res <- rawConnectionValue(rc); close(rc); res } + [1] 32 63 20 32 30 20 35 37 20 36 66 20 37 32 0a 36 63 20 36 34 0a + +##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadWriteText# +#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "r+"); write(charToRaw(", World"), rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res } +[1] "2c 20 57 6f 72\n6c 64\n" + +##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadWriteText# +#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "r+"); writeChar(", World", rc); res <- rawConnectionValue(rc); close(rc); res } +[1] 2c 20 57 6f 72 6c 64 00 + +##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadWriteText# +#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "r+"); writeChar(", World", rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res } +[1] ", World" + +##com.oracle.truffle.r.test.library.base.TestConnections.testRawWriteBinary#Ignored.ImplementationError# +#conn <- rawConnection(raw(0), "w"); value <- c(1,2,3); save(value, file=conn); rawConnectionValue(conn) + [1] 52 44 58 32 0a 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 04 02 00 00 +[26] 00 01 00 04 00 09 00 00 00 05 76 61 6c 75 65 00 00 00 0e 00 00 00 03 3f f0 +[51] 00 00 00 00 00 00 40 00 00 00 00 00 00 00 40 08 00 00 00 00 00 00 00 00 00 +[76] fe + +##com.oracle.truffle.r.test.library.base.TestConnections.testRawWriteBinary# +#conn <- rawConnection(raw(0), "wb"); value <- list(a=c(1,2,3), b='foo'); save(value, file=conn); rawConnectionValue(conn) + [1] 52 44 58 32 0a 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 04 02 00 00 + [26] 00 01 00 04 00 09 00 00 00 05 76 61 6c 75 65 00 00 02 13 00 00 00 02 00 00 + [51] 00 0e 00 00 00 03 3f f0 00 00 00 00 00 00 40 00 00 00 00 00 00 00 40 08 00 + [76] 00 00 00 00 00 00 00 00 10 00 00 00 01 00 04 00 09 00 00 00 03 66 6f 6f 00 +[101] 00 04 02 00 00 00 01 00 04 00 09 00 00 00 05 6e 61 6d 65 73 00 00 00 10 00 +[126] 00 00 02 00 04 00 09 00 00 00 01 61 00 04 00 09 00 00 00 01 62 00 00 00 fe +[151] 00 00 00 fe + +##com.oracle.truffle.r.test.library.base.TestConnections.testRawWriteBinary#Ignored.ImplementationError# +#{ s <- "äöüß"; rc <- rawConnection(raw(0), "wb"); write(charToRaw(s), rc); res <- rawConnectionValue(rc); close(rc); res } + [1] 63 33 20 61 34 20 63 33 20 62 36 20 63 33 0a 62 63 20 63 33 20 39 66 0a + +##com.oracle.truffle.r.test.library.base.TestConnections.testRawWriteBinary# +#{ zz <- rawConnection(raw(0), "wb"); x <- c("a", "this will be truncated", "abc"); nc <- c(3, 10, 3); writeChar(x, zz, nc, eos = NULL); writeChar(x, zz, eos = "\r\n"); res <- rawConnectionValue(zz); close(zz); res } + [1] 61 00 00 74 68 69 73 20 77 69 6c 6c 20 61 62 63 61 0d 0a 00 74 68 69 73 20 +[26] 77 69 6c 6c 20 62 65 20 74 72 75 6e 63 61 74 65 64 0d 0a 00 61 62 63 0d 0a +[51] 00 +Warning message: +In writeChar(x, zz, nc, eos = NULL) : + writeChar: more characters requested than are in the string - will zero-pad + +##com.oracle.truffle.r.test.library.base.TestConnections.testRawWriteText# +#{ rc <- rawConnection(raw(0), "w"); writeChar("Hello", rc); writeChar(", World", rc); res <- rawConnectionValue(rc); close(rc); res } + [1] 48 65 6c 6c 6f 00 2c 20 57 6f 72 6c 64 00 + +##com.oracle.truffle.r.test.library.base.TestConnections.testRawWriteText# +#{ s <- "äöüß"; rc <- rawConnection(raw(0), "w"); writeChar(s, rc); rawConnectionValue(rc) } +[1] c3 a4 c3 b6 c3 bc c3 9f 00 + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); res } +[1] "abcd" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); res } +[1] "abcde" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); res } +[1] "abcd" +Warning messages: +1: In readLines(zz, 2, warn = T, skipNul = F) : + line 1 appears to contain an embedded nul +2: In readLines(zz, 2, warn = T, skipNul = F) : + incomplete final line found on '' + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); res } +[1] "abcde" +Warning message: +In readLines(zz, 2, warn = T, skipNul = T) : + incomplete final line found on '' + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); res } +[1] "abcd" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); res } +[1] "abcde" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); res } +[1] "abcd" +Warning message: +In readLines(zz, 2, warn = T, skipNul = F) : + line 1 appears to contain an embedded nul + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); res } +[1] "abcde" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); res } +[1] "abcd" "ABC" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); res } +[1] "abcde" "ABC" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); res } +[1] "abcd" "ABC" +Warning messages: +1: In readLines(zz, 2, warn = T, skipNul = F) : + line 1 appears to contain an embedded nul +2: In readLines(zz, 2, warn = T, skipNul = F) : + incomplete final line found on '' + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); res } +[1] "abcde" "ABC" +Warning message: +In readLines(zz, 2, warn = T, skipNul = T) : + incomplete final line found on '' + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); res } +[1] "abcd" "ABC" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); res } +[1] "abcde" "ABC" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); res } +[1] "abcd" "ABC" +Warning message: +In readLines(zz, 2, warn = T, skipNul = F) : + line 1 appears to contain an embedded nul + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); res } +[1] "abcde" "ABC" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); res } +[1] "abcd" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); res } +[1] "abcde" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); res } +[1] "abcd" +Warning messages: +1: In readLines(zz, 2, warn = T, skipNul = F) : + line 1 appears to contain an embedded nul +2: In readLines(zz, 2, warn = T, skipNul = F) : + incomplete final line found on '' + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); res } +[1] "abcde" +Warning message: +In readLines(zz, 2, warn = T, skipNul = T) : + incomplete final line found on '' + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); res } +[1] "abcd" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); res } +[1] "abcde" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); res } +[1] "abcd" +Warning message: +In readLines(zz, 2, warn = T, skipNul = F) : + line 1 appears to contain an embedded nul + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); res } +[1] "abcde" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); res } +[1] "abcd" "ABC" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); res } +[1] "abcde" "ABC" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); res } +[1] "abcd" "ABC" +Warning messages: +1: In readLines(zz, 2, warn = T, skipNul = F) : + line 1 appears to contain an embedded nul +2: In readLines(zz, 2, warn = T, skipNul = F) : + incomplete final line found on '' + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); res } +[1] "abcde" "ABC" +Warning message: +In readLines(zz, 2, warn = T, skipNul = T) : + incomplete final line found on '' + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); res } +[1] "abcd" "ABC" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); res } +[1] "abcde" "ABC" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); res } +[1] "abcd" "ABC" +Warning message: +In readLines(zz, 2, warn = T, skipNul = F) : + line 1 appears to contain an embedded nul + +##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext# +#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); res } +[1] "abcde" "ABC" + +##com.oracle.truffle.r.test.library.base.TestConnections.testReopen# +#{ con <- rawConnection(charToRaw('hello\nworld\n')); readLines(con, 1); open(con, 'rb'); bin <- readBin(con, raw(), 999); close(con); rawToChar(bin) } +[1] "world\n" +Warning message: +In open.connection(con, "rb") : connection is already open + +##com.oracle.truffle.r.test.library.base.TestConnections.testSeekTextConnection# +#{ zz <- textConnection("Hello, World!"); res <- isSeekable(zz); close(zz); res } +[1] FALSE + +##com.oracle.truffle.r.test.library.base.TestConnections.testSeekTextConnection#Output.IgnoreErrorMessage# +#{ zz <- textConnection("Hello, World!"); res <- seek(zz, 5); close(zz); res } +Error in seek.connection(zz, 5) : + seek is not relevant for text connection + +##com.oracle.truffle.r.test.library.base.TestConnections.testTextReadConnection#Output.IgnoreErrorContext# +#textConnection(NULL, 'r') +Error in textConnection(NULL, "r") : invalid 'text' argument + ##com.oracle.truffle.r.test.library.base.TestConnections.testTextReadConnection# #{ con <- textConnection(c("1", "2", "3","4")); readLines(con) } [1] "1" "2" "3" "4" @@ -73417,25 +78228,29 @@ numeric(0) #{ con <- textConnection(c("1", "2", "3","4")); readLines(con, 2); readLines(con, 2); readLines(con, 2) } character(0) -##com.oracle.truffle.r.test.library.base.TestConnections.testWriteConnection#Ignored.Unimplemented# +##com.oracle.truffle.r.test.library.base.TestConnections.testWriteTextConnection# #c <- textConnection('out', 'w'); cat('testtext', file=c); isIncomplete(c); cat('testtext2\n', file=c); isIncomplete(c); close(c); out [1] TRUE [1] FALSE [1] "testtexttesttext2" -##com.oracle.truffle.r.test.library.base.TestConnections.testWriteConnection# +##com.oracle.truffle.r.test.library.base.TestConnections.testWriteTextConnection# +#{ c <- textConnection(NULL, 'w'); cat('testtext\n', file=c); textConnectionValue(c) } +[1] "testtext" + +##com.oracle.truffle.r.test.library.base.TestConnections.testWriteTextConnection# #{ con <- textConnection("tcval", open="w"); writeLines("a", con); tcval; close(con) } -##com.oracle.truffle.r.test.library.base.TestConnections.testWriteConnection# +##com.oracle.truffle.r.test.library.base.TestConnections.testWriteTextConnection# #{ con <- textConnection("tcval", open="w"); writeLines("a", con); writeLines(c("a", "b"), con, sep="."); tcval; close(con) } -##com.oracle.truffle.r.test.library.base.TestConnections.testWriteConnection# +##com.oracle.truffle.r.test.library.base.TestConnections.testWriteTextConnection# #{ con <- textConnection("tcval", open="w"); writeLines("a", con); writeLines(c("a", "b"), con, sep="."); writeLines("", con); tcval; close(con) } -##com.oracle.truffle.r.test.library.base.TestConnections.testWriteConnection# +##com.oracle.truffle.r.test.library.base.TestConnections.testWriteTextConnection# #{ con <- textConnection("tcval", open="w"); writeLines("a\nb", con); tcval; close(con) } -##com.oracle.truffle.r.test.library.base.TestConnections.testWriteConnection# +##com.oracle.truffle.r.test.library.base.TestConnections.testWriteTextConnection# #{ d<-data.frame(c(1,2), c(10, 20)); buf<-character(); c<-textConnection("buf", open="w", local=T); write.table(d, c); buf } [1] "\"c.1..2.\" \"c.10..20.\"" "\"1\" 1 10" [3] "\"2\" 2 20" @@ -74252,6 +79067,10 @@ Error in get("x") : object 'x' not found #{ x <- function(){3} ; gg <- function() { assign("x", 4) ; g <- function() { if (FALSE) { x <- 2 } ; f <- function() { h <- function() { x() } ; h() } ; f() } ; g() } ; gg() } [1] 3 +##com.oracle.truffle.r.test.library.base.TestPromiseOptimizations.testDeoptimization# +#{ delayedAssign('x', c(1,2,3)); x/180; x } +[1] 1 2 3 + ##com.oracle.truffle.r.test.library.base.TestPromiseOptimizations.testDeoptimization# #{ f <- function(x) { assign('e', function() {x}, parent.frame()) } ; a <- 1 ; f( a ) ; a <- 10 ; e() } [1] 10 @@ -74292,6 +79111,10 @@ Error in get("x") : object 'x' not found #{ f <- function(x) { sys.frame(sys.nframe()) } ; a <- 1 ; e <- f( a ) ; a <- 10 ; e$x } [1] 10 +##com.oracle.truffle.r.test.library.base.TestPromiseOptimizations.testDeoptimization# +#{ pi/180; pi } +[1] 3.141593 + ##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 @@ -74935,35 +79758,35 @@ Error in c(1, 0) && "1" : invalid 'y' type in 'x && y' #{ f <- function(a,b) { a && b } ; f(c(TRUE, FALSE), logical()) } [1] NA -##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks# #{ as.raw(c(1,4)) | as.raw(c(1,5,4)) } [1] 01 05 05 Warning message: In as.raw(c(1, 4)) | as.raw(c(1, 5, 4)) : longer object length is not a multiple of shorter object length -##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks# #{ as.raw(c(1,5,4)) | as.raw(c(1,4)) } [1] 01 05 05 Warning message: In as.raw(c(1, 5, 4)) | as.raw(c(1, 4)) : longer object length is not a multiple of shorter object length -##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks# #{ c(TRUE, FALSE, FALSE) & c(TRUE,TRUE) } [1] TRUE FALSE FALSE Warning message: In c(TRUE, FALSE, FALSE) & c(TRUE, TRUE) : longer object length is not a multiple of shorter object length -##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks# #{ c(TRUE, TRUE) & c(TRUE, FALSE, FALSE) } [1] TRUE FALSE FALSE Warning message: In c(TRUE, TRUE) & c(TRUE, FALSE, FALSE) : longer object length is not a multiple of shorter object length -##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks# #{ c(a=TRUE, TRUE) | c(TRUE, b=FALSE, FALSE) } b TRUE TRUE TRUE @@ -76174,28 +80997,28 @@ numeric(0) #{ c(3,4) %/% 2 } [1] 1 2 -##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testVectorsLengthWarning#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testVectorsLengthWarning# #{ 1:2+1:3 } [1] 2 4 4 Warning message: In 1:2 + 1:3 : longer object length is not a multiple of shorter object length -##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testVectorsLengthWarning#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testVectorsLengthWarning# #{ 1:3*1:2 } [1] 1 4 3 Warning message: In 1:3 * 1:2 : longer object length is not a multiple of shorter object length -##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testVectorsLengthWarning#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testVectorsLengthWarning# #{ 1:3+c(1,2+2i) } [1] 2+0i 4+2i 4+0i Warning message: In 1:3 + c(1, 2 + (0+2i)) : longer object length is not a multiple of shorter object length -##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testVectorsLengthWarning#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testVectorsLengthWarning# #{ c(1,2+2i)+1:3 } [1] 2+0i 4+2i 4+0i Warning message: @@ -76738,11 +81561,11 @@ Error in x[[, 1, 1]] : invalid subscript type 'symbol' #{ a = array(1:10, dim = c(2,6)); length(a) } [1] 12 -##com.oracle.truffle.r.test.library.base.TestSimpleArrays.testArrayBuiltin#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleArrays.testArrayBuiltin# #{ array(NA, dim=c(-2,-2)); } Error in array(NA, dim = c(-2, -2)) : the dims contain negative values -##com.oracle.truffle.r.test.library.base.TestSimpleArrays.testArrayBuiltin#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleArrays.testArrayBuiltin# #{ array(NA, dim=c(-2,2)); } Error in array(NA, dim = c(-2, 2)) : negative length vectors are not allowed @@ -79027,14 +83850,14 @@ logical(0) #{ TRUE == 1:3 } [1] TRUE FALSE FALSE -##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors# #{ as.raw(c(1,2)) < as.raw(c(2,1,4)) } [1] TRUE FALSE TRUE Warning message: In as.raw(c(1, 2)) < as.raw(c(2, 1, 4)) : longer object length is not a multiple of shorter object length -##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors# #{ as.raw(c(2,1,4)) < as.raw(c(1,2)) } [1] FALSE TRUE FALSE Warning message: @@ -79049,7 +83872,7 @@ logical(0) #{ b <- 1:3 ; z <- FALSE ; b[2==2] } [1] 1 2 3 -##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors# #{ c("cau", "ahoj") != c("hi","hello","bye") } [1] TRUE TRUE TRUE Warning message: @@ -79076,7 +83899,7 @@ logical(0) #{ c("hello", NA) >= "hi" } [1] FALSE NA -##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors# #{ c("hi","hello","bye") > c("cau", "ahoj") } [1] TRUE TRUE FALSE Warning message: @@ -79091,7 +83914,7 @@ In c("hi", "hello", "bye") > c("cau", "ahoj") : #{ c(1+1i,2+1i) == c(0/0+1i,2+1i) } [1] NA TRUE -##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors# #{ c(1+1i,2+2i) == c(2+1i,1+2i,1+1i) } [1] FALSE FALSE TRUE Warning message: @@ -79102,7 +83925,7 @@ In c(1 + (0+1i), 2 + (0+2i)) == c(2 + (0+1i), 1 + (0+2i), 1 + (0+1i)) : #{ c(1+2i, 3+4i) == (1+2i)[0] } logical(0) -##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors# #{ c(1,2) < c(2,1,4) } [1] TRUE FALSE TRUE Warning message: @@ -79133,7 +83956,7 @@ logical(0) #{ c(1L, NA) > c(NA, 2L) } [1] NA NA -##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors# #{ c(1L,2L) < c(2L,1L,4L) } [1] TRUE FALSE TRUE Warning message: @@ -79144,21 +83967,21 @@ In c(1L, 2L) < c(2L, 1L, 4L) : #{ c(1L,NA,2L) < 2L } [1] TRUE NA FALSE -##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors# #{ c(2+1i,1+2i,1+1i) == c(1+1i, 2+2i) } [1] FALSE FALSE TRUE Warning message: In c(2 + (0+1i), 1 + (0+2i), 1 + (0+1i)) == c(1 + (0+1i), 2 + (0+2i)) : longer object length is not a multiple of shorter object length -##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors# #{ c(2,1,4) < c(1,2) } [1] FALSE TRUE FALSE Warning message: In c(2, 1, 4) < c(1, 2) : longer object length is not a multiple of shorter object length -##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors# #{ c(2L,1L,4L) < c(1L,2L) } [1] FALSE TRUE FALSE Warning message: @@ -79173,14 +83996,14 @@ In c(2L, 1L, 4L) < c(1L, 2L) : #{ c(TRUE,FALSE) < logical() } logical(0) -##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors# #{ c(TRUE,FALSE,FALSE) < c(TRUE,TRUE) } [1] FALSE TRUE TRUE Warning message: In c(TRUE, FALSE, FALSE) < c(TRUE, TRUE) : longer object length is not a multiple of shorter object length -##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors# #{ c(TRUE,TRUE) == c(TRUE,FALSE,FALSE) } [1] TRUE FALSE FALSE Warning message: @@ -79476,7 +84299,7 @@ $class #{ x<-as.raw(c(7L,42L)); y<-as.data.frame(x, row.names=NULL, nm="x"); is.data.frame(y); } [1] TRUE -##com.oracle.truffle.r.test.library.base.TestSimpleDataFrames.testAsDataFrame#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleDataFrames.testAsDataFrame#Output.MayIgnoreWarningContext# #{ x<-c(7L,42L); y<-as.data.frame(x, row.names="r1", nm="x"); attributes(y); } $names [1] "x" @@ -79519,7 +84342,7 @@ $class [1] "data.frame" -##com.oracle.truffle.r.test.library.base.TestSimpleDataFrames.testAsDataFrame#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleDataFrames.testAsDataFrame#Output.MayIgnoreWarningContext# #{ x<-c(7L,42L); y<-as.data.frame(x, row.names=c("r1", "r2", "r3"), nm="x"); attributes(y); } $names [1] "x" @@ -79661,6 +84484,11 @@ $x [1] FALSE TRUE TRUE +##com.oracle.truffle.r.test.library.base.TestSimpleDataFrames.testMisc# +#x <- data.frame(a=1:3,b=factor(c("a","b","c"))); x[2,] + a b +2 2 b + ##com.oracle.truffle.r.test.library.base.TestSimpleDataFrames.testMisc# #{ y<-data.frame(7); as.logical(y) } [1] TRUE @@ -79929,74 +84757,74 @@ Error: object 'v' not found #{ typeof(a~b) } [1] "language" -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast# #{ f <- function(a) { if (is.na(a)) { 1 } else { 2 } } ; f(5) ; f(1:3)} [1] 2 Warning message: In if (is.na(a)) { : the condition has length > 1 and only the first element will be used -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast# #{ f <- function(cond) { if (cond) { TRUE } else { 2 } } ; f(c(TRUE,FALSE)) ; f(1) } [1] TRUE Warning message: In if (cond) { : the condition has length > 1 and only the first element will be used -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast# #{ f <- function(cond) { if (cond) { TRUE } else { 2 } } ; f(c(TRUE,FALSE)) ; f(FALSE) } [1] 2 Warning message: In if (cond) { : the condition has length > 1 and only the first element will be used -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast# #{ f <- function(cond) { if (cond) { TRUE } else { 2 } } ; f(logical()) } Error in if (cond) { : argument is of length zero -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast# #{ f <- function(cond) { if (cond) { TRUE } else { 2 } } ; f(1:3) ; f(2) } [1] TRUE Warning message: In if (cond) { : the condition has length > 1 and only the first element will be used -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast# #{ if (1:3) { TRUE } } [1] TRUE Warning message: In if (1:3) { : the condition has length > 1 and only the first element will be used -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast# #{ if (1[2:1]) { TRUE } } Error in if (1[2:1]) { : argument is not interpretable as logical In addition: Warning message: In if (1[2:1]) { : the condition has length > 1 and only the first element will be used -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast# #{ if (c(0,0,0)) { TRUE } else { 2 } } [1] 2 Warning message: In if (c(0, 0, 0)) { : the condition has length > 1 and only the first element will be used -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast# #{ if (c(0L,0L,0L)) { TRUE } else { 2 } } [1] 2 Warning message: In if (c(0L, 0L, 0L)) { : the condition has length > 1 and only the first element will be used -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast# #{ if (c(1L,0L,0L)) { TRUE } else { 2 } } [1] TRUE Warning message: In if (c(1L, 0L, 0L)) { : the condition has length > 1 and only the first element will be used -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast# #{ if (c(1L[2],0L,0L)) { TRUE } else { 2 } } Error in if (c(1L[2], 0L, 0L)) { : argument is not interpretable as logical @@ -80004,7 +84832,7 @@ In addition: Warning message: In if (c(1L[2], 0L, 0L)) { : the condition has length > 1 and only the first element will be used -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast# #{ if (integer()) { TRUE } } Error in if (integer()) { : argument is of length zero @@ -80012,11 +84840,11 @@ Error in if (integer()) { : argument is of length zero #{ f <- function(v) { if (FALSE==v) TRUE else FALSE } ; f(TRUE) ; f(1) } [1] FALSE -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf# #{ f <- function(x) { if (x == 2) 1 else 2 } ; f(1) ; f(NA) } Error in if (x == 2) 1 else 2 : missing value where TRUE/FALSE needed -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf# #{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f("hello") } Error in if (x) 1 else 2 : argument is not interpretable as logical @@ -80024,7 +84852,7 @@ Error in if (x) 1 else 2 : argument is not interpretable as logical #{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(FALSE) } [1] 2 -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf# #{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(NA) } Error in if (x) 1 else 2 : missing value where TRUE/FALSE needed @@ -80032,11 +84860,11 @@ Error in if (x) 1 else 2 : missing value where TRUE/FALSE needed #{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(TRUE) } [1] 1 -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf# #{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(logical()) } Error in if (x) 1 else 2 : argument is of length zero -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf# #{ f <- function(x) { if (x) 1 else 2 } ; f(NA) } Error in if (x) 1 else 2 : missing value where TRUE/FALSE needed @@ -80052,12 +84880,12 @@ Error in if (x) 1 else 2 : missing value where TRUE/FALSE needed #{ if (FALSE==TRUE) TRUE else FALSE } [1] FALSE -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf# #{ if (NA == TRUE) TRUE else FALSE } Error in if (NA == TRUE) TRUE else FALSE : missing value where TRUE/FALSE needed -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf# #{ if (TRUE == NA) TRUE else FALSE } Error in if (TRUE == NA) TRUE else FALSE : missing value where TRUE/FALSE needed @@ -80070,11 +84898,11 @@ Error in if (TRUE == NA) TRUE else FALSE : #{ x <- 2 ; if (1==x) TRUE else 2 } [1] 2 -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf# #{ x <- 2 ; if (NA) x <- 3 ; x } Error in if (NA) x <- 3 : missing value where TRUE/FALSE needed -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#Output.IgnoreErrorContext#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf# #{ x<-list(1,2); if (x) 7 else 42 } Error in if (x) 7 else 42 : argument is not interpretable as logical In addition: Warning message: @@ -80096,7 +84924,7 @@ In if (x) 7 else 42 : ##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIfDanglingElseIgnore# #if(FALSE) if (FALSE) 1 else 2 -##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIfIgnore#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIfIgnore# #{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(1:3) } [1] 1 Warning message: @@ -80227,6 +85055,12 @@ NULL NULL +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListAccess# +#{ l <- list(1,2,3) ; l[NaN] } +[[1]] +NULL + + ##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListAccess#Output.IgnoreErrorContext# #{ l <- list(1,2,3) ; l[[-2]] } Error in l[[-2]] : @@ -80250,6 +85084,10 @@ Error in l[[5]] : subscript out of bounds #{ l <- list(1,2,3) ; l[[NA]] } NULL +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListAccess# +#{ l <- list(1,2,3) ; l[[NaN]] } +NULL + ##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListAccess# #{ l <- list(1,2,3) ; typeof(l[-2]) } [1] "list" @@ -80262,10 +85100,18 @@ NULL #{ l <- list(1,2,3) ; typeof(l[NA]) } [1] "list" +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListAccess# +#{ l <- list(1,2,3) ; typeof(l[NaN]) } +[1] "list" + ##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListAccess# #{ l <- list(1,2,3) ; typeof(l[[NA]]) } [1] "NULL" +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListAccess# +#{ l <- list(1,2,3) ; typeof(l[[NaN]]) } +[1] "NULL" + ##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListAccess# #{ l <- list(c(1,2,3),"eep") ; l[[1]] } [1] 1 2 3 @@ -80652,7 +85498,7 @@ $z #a<- NULL; a <- `$<-`(a, "a", 1); dput(a) structure(list(a = 1), .Names = "a") -##com.oracle.truffle.r.test.library.base.TestSimpleLists.testNullListAssignment# +##com.oracle.truffle.r.test.library.base.TestSimpleLists.testNullListAssignment#Output.IgnoreErrorContext# #a<- NULL; a <- `$<-`(a, 1, 1); dput(a) Error: invalid subscript type 'double' @@ -80804,7 +85650,7 @@ Error: unexpected '$' in "{ next(1,2,$" #{ next; } Error: no loop for break/next, jumping to top level -##com.oracle.truffle.r.test.library.base.TestSimpleLoop.testLoopsErrors#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleLoop.testLoopsErrors# #{ while (1 < NA) { 1 } } Error in while (1 < NA) { : missing value where TRUE/FALSE needed @@ -80999,18 +85845,34 @@ a 1 NA [1,] 1 3 [2,] NA NA +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-(1:4); dim(x)<-c(2,2); x[c(1, NaN), ] } + [,1] [,2] +[1,] 1 3 +[2,] NA NA + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-(1:4); dim(x)<-c(2,2); x[c(TRUE, NA), ] } [,1] [,2] [1,] 1 3 [2,] NA NA +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-(1:4); dim(x)<-c(2,2); x[c(TRUE, NaN), ] } + [,1] [,2] +[1,] 1 3 +[2,] NA NA + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-(1:4); x<-1:4; dim(x)<-c(2,2); x[NA, ] } [,1] [,2] [1,] NA NA [2,] NA NA +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-(1:4); x<-1:4; dim(x)<-c(2,2); x[NaN, ] } +[1] NA NA + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-(1:8); dim(x)<-c(2, 4); x[c(-1, -2),c(-1)] } [,1] [,2] [,3] @@ -81344,18 +86206,34 @@ a "a" NA [1,] "a" "c" [2,] NA NA +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-c("a", "b", "c", "d"); dim(x)<-c(2,2); x[c(1, NaN), ] } + [,1] [,2] +[1,] "a" "c" +[2,] NA NA + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-c("a", "b", "c", "d"); dim(x)<-c(2,2); x[c(TRUE, NA), ] } [,1] [,2] [1,] "a" "c" [2,] NA NA +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-c("a", "b", "c", "d"); dim(x)<-c(2,2); x[c(TRUE, NaN), ] } + [,1] [,2] +[1,] "a" "c" +[2,] NA NA + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-c("a", "b", "c", "d"); x<-1:4; dim(x)<-c(2,2); x[NA, ] } [,1] [,2] [1,] NA NA [2,] NA NA +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-c("a", "b", "c", "d"); x<-1:4; dim(x)<-c(2,2); x[NaN, ] } +[1] NA NA + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-c(1+1i, 2+2i, 3+3i, 4+4i); dim(x)<-c(1,4); dimnames(x)<-list("z", c("a", "b", "c", "d")); x[, 0] } complex(0) @@ -81480,18 +86358,34 @@ a 1+1i NA [1,] 1+1i 3+3i [2,] NA NA +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-c(1+1i, 2+2i, 3+3i, 4+4i); dim(x)<-c(2,2); x[c(1, NaN), ] } + [,1] [,2] +[1,] 1+1i 3+3i +[2,] NA NA + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-c(1+1i, 2+2i, 3+3i, 4+4i); dim(x)<-c(2,2); x[c(TRUE, NA), ] } [,1] [,2] [1,] 1+1i 3+3i [2,] NA NA +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-c(1+1i, 2+2i, 3+3i, 4+4i); dim(x)<-c(2,2); x[c(TRUE, NaN), ] } + [,1] [,2] +[1,] 1+1i 3+3i +[2,] NA NA + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-c(1+1i, 2+2i, 3+3i, 4+4i); x<-1:4; dim(x)<-c(2,2); x[NA, ] } [,1] [,2] [1,] NA NA [2,] NA NA +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-c(1+1i, 2+2i, 3+3i, 4+4i); x<-1:4; dim(x)<-c(2,2); x[NaN, ] } +[1] NA NA + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-c(1+1i, 2+2i, 3+3i, 4+4i, 5+5i, 6+6i, 7+7i, 8+8i); dim(x)<-c(2, 4); x[c(-1, -2),c(-1)] } [,1] [,2] [,3] @@ -81702,18 +86596,34 @@ a 1.1 NA [1,] 1.1 3.3 [2,] NA NA +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-c(1.1, 2.2, 3.3, 4.4); dim(x)<-c(2,2); x[c(1, NaN), ] } + [,1] [,2] +[1,] 1.1 3.3 +[2,] NA NA + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-c(1.1, 2.2, 3.3, 4.4); dim(x)<-c(2,2); x[c(TRUE, NA), ] } [,1] [,2] [1,] 1.1 3.3 [2,] NA NA +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-c(1.1, 2.2, 3.3, 4.4); dim(x)<-c(2,2); x[c(TRUE, NaN), ] } + [,1] [,2] +[1,] 1.1 3.3 +[2,] NA NA + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-c(1.1, 2.2, 3.3, 4.4); x<-1:4; dim(x)<-c(2,2); x[NA, ] } [,1] [,2] [1,] NA NA [2,] NA NA +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-c(1.1, 2.2, 3.3, 4.4); x<-1:4; dim(x)<-c(2,2); x[NaN, ] } +[1] NA NA + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-c(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8); dim(x)<-c(2, 4); x[c(-1, -2),c(-1)] } [,1] [,2] [,3] @@ -81932,18 +86842,34 @@ TRUE NA [1,] TRUE TRUE [2,] NA NA +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-c(TRUE, FALSE, TRUE, FALSE); dim(x)<-c(2,2); x[c(1, NaN), ] } + [,1] [,2] +[1,] TRUE TRUE +[2,] NA NA + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-c(TRUE, FALSE, TRUE, FALSE); dim(x)<-c(2,2); x[c(TRUE, NA), ] } [,1] [,2] [1,] TRUE TRUE [2,] NA NA +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-c(TRUE, FALSE, TRUE, FALSE); dim(x)<-c(2,2); x[c(TRUE, NaN), ] } + [,1] [,2] +[1,] TRUE TRUE +[2,] NA NA + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-c(TRUE, FALSE, TRUE, FALSE); x<-1:4; dim(x)<-c(2,2); x[NA, ] } [,1] [,2] [1,] NA NA [2,] NA NA +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-c(TRUE, FALSE, TRUE, FALSE); x<-1:4; dim(x)<-c(2,2); x[NaN, ] } +[1] NA NA + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-c(as.raw(1),as.raw(2),as.raw(3),as.raw(4)); dim(x)<-c(1,4); dimnames(x)<-list("z", c("a", "b", "c", "d")); x[, 0] } raw(0) @@ -82064,18 +86990,34 @@ a 01 00 [1,] 01 03 [2,] 00 00 +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-c(as.raw(1),as.raw(2),as.raw(3),as.raw(4)); dim(x)<-c(2,2); x[c(1, NaN), ] } + [,1] [,2] +[1,] 01 03 +[2,] 00 00 + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-c(as.raw(1),as.raw(2),as.raw(3),as.raw(4)); dim(x)<-c(2,2); x[c(TRUE, NA), ] } [,1] [,2] [1,] 01 03 [2,] 00 00 +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-c(as.raw(1),as.raw(2),as.raw(3),as.raw(4)); dim(x)<-c(2,2); x[c(TRUE, NaN), ] } + [,1] [,2] +[1,] 01 03 +[2,] 00 00 + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-c(as.raw(1),as.raw(2),as.raw(3),as.raw(4)); x<-1:4; dim(x)<-c(2,2); x[NA, ] } [,1] [,2] [1,] NA NA [2,] NA NA +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-c(as.raw(1),as.raw(2),as.raw(3),as.raw(4)); x<-1:4; dim(x)<-c(2,2); x[NaN, ] } +[1] NA NA + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-list(TRUE, "a", 42, 1.1); dim(x)<-c(1,4); dimnames(x)<-list("z", c("a", "b", "c", "d")); x[, 0] } list() @@ -82238,18 +87180,34 @@ NULL [1,] TRUE 42 [2,] NULL NULL +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-list(TRUE, "a", 42, 1.1); dim(x)<-c(2,2); x[c(1, NaN), ] } + [,1] [,2] +[1,] TRUE 42 +[2,] NULL NULL + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-list(TRUE, "a", 42, 1.1); dim(x)<-c(2,2); x[c(TRUE, NA), ] } [,1] [,2] [1,] TRUE 42 [2,] NULL NULL +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-list(TRUE, "a", 42, 1.1); dim(x)<-c(2,2); x[c(TRUE, NaN), ] } + [,1] [,2] +[1,] TRUE 42 +[2,] NULL NULL + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# #{ x<-list(TRUE, "a", 42, 1.1); x<-1:4; dim(x)<-c(2,2); x[NA, ] } [,1] [,2] [1,] NA NA [2,] NA NA +##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex# +#{ x<-list(TRUE, "a", 42, 1.1); x<-1:4; dim(x)<-c(2,2); x[NaN, ] } +[1] NA NA + ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testMatrixAccessWithScalarAndVector# #{ i <- c(1L,3L,5L) ; m <- 1:10 ; dim(m) <- c(2,5) ; m[2,i] } [1] 2 6 10 @@ -82773,7 +87731,7 @@ In addition: Warning messages: 2: In c(1, 2) < c(1, 3, 4) : longer object length is not a multiple of shorter object length -##com.oracle.truffle.r.test.library.base.TestSimpleTruffle.testWarningsAndErrors#Output.IgnoreErrorContext#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleTruffle.testWarningsAndErrors# #{ 1i > (c(1, 2) < c(1, 2, 3)) } Error in 0+1i > (c(1, 2) < c(1, 2, 3)) : invalid comparison with complex values @@ -114773,7 +119731,7 @@ Error in x[["a", "d"]] : subscript out of bounds #{ c("1L","hello") %in% 1:10 } [1] FALSE FALSE -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testIn#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testIn# #{ x <- function(){1} ; x %in% TRUE } Error in match(x, table, nomatch = 0L) : 'match' requires vector arguments @@ -114802,6 +119760,18 @@ Error in match(x, table, nomatch = 0L) : #{ x<-quote(function(x, y) 42); typeof(x[[2]][[1]]) } [1] "symbol" +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testLanguageIndex# +#{ x<-quote(function(x, y) 42); x[2] } +pairlist(x = , y = )() + +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testLanguageIndex# +#{ x<-quote(function(x, y) 42); x[NA] } +NULL(NULL, NULL, NULL) + +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testLanguageIndex# +#{ x<-quote(function(x, y) 42); x[NaN] } +NULL() + ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testLanguageIndex# #{ x<-quote(function(x, y) 42); x[[2]] } $x @@ -117115,6 +122085,10 @@ NULL #{ x<-NULL; x[3L] } NULL +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectors# +#{ x<-NULL; x[NaN] } +NULL + ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# #{ b <- as.list(3:5) ; dim(b) <- c(1,3) ; b[NULL] <- NULL ; b } [,1] [,2] [,3] @@ -117755,7 +122729,7 @@ Error in x[[c(TRUE, TRUE)]] : #{ x<-1:4; x[c(0, 1)]<-42; x } [1] 42 2 3 4 -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# #{ x<-1:4; x[c(0, 1)]<-c(7, 42); x } [1] 7 2 3 4 Warning message: @@ -117766,13 +122740,29 @@ In x[c(0, 1)] <- c(7, 42) : #{ x<-1:4; x[c(1, 0)]<-42; x } [1] 42 2 3 4 -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# #{ x<-1:4; x[c(1, 0)]<-c(7, 42); x } [1] 7 2 3 4 Warning message: In x[c(1, 0)] <- c(7, 42) : number of items to replace is not a multiple of replacement length +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# +#{ x<-1:4; x[c(1, NA)]<-42; x } +[1] 42 2 3 4 + +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# +#{ x<-1:4; x[c(1, NaN)]<-42; x } +[1] 42 2 3 4 + +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# +#{ x<-1:4; x[c(NA, 1)]<-42; x } +[1] 42 2 3 4 + +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# +#{ x<-1:4; x[c(NaN, 1)]<-42; x } +[1] 42 2 3 4 + ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# #{ x<-1:4; dim(x)<-c(2,2); x[NA, NA]<-7; x } [,1] [,2] @@ -118038,7 +123028,7 @@ Error in `[[<-`(`*tmp*`, list(1, 2, 3), value = c(42, 43)) : [1,] 1 3 [2,] 2 4 -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# #{ x<-1:4; dim(x)<-c(2,2); x[c(0,0,1)]<-c(42, 43); x } [,1] [,2] [1,] 42 3 @@ -118047,7 +123037,7 @@ Warning message: In x[c(0, 0, 1)] <- c(42, 43) : number of items to replace is not a multiple of replacement length -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# #{ x<-1:4; dim(x)<-c(2,2); x[c(0,1)]<-c(42, 43); x } [,1] [,2] [1,] 42 3 @@ -118096,7 +123086,7 @@ Error in x[c(1 + (0+1i), 42 + (0+7i), 3 + (0+3i))] <- c(42, 43) : [1,] 7 3 [2,] 2 4 -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# #{ x<-1:4; dim(x)<-c(2,2); x[c(1,0)]<-c(42, 43); x } [,1] [,2] [1,] 42 3 @@ -118105,7 +123095,7 @@ Warning message: In x[c(1, 0)] <- c(42, 43) : number of items to replace is not a multiple of replacement length -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# #{ x<-1:4; dim(x)<-c(2,2); x[c(1,0,0)]<-c(42, 43); x } [,1] [,2] [1,] 42 3 @@ -118131,6 +123121,11 @@ In x[c(1, 0, 0)] <- c(42, 43) : Error in x[c(1, NA)] <- c(42, 43) : NAs are not allowed in subscripted assignments +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# +#{ x<-1:4; dim(x)<-c(2,2); x[c(1,NaN)]<-c(42, 43); x } +Error in x[c(1, NaN)] <- c(42, 43) : + NAs are not allowed in subscripted assignments + ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# #{ x<-1:4; dim(x)<-c(2,2); x[c(NA, 1),1]<-7; x } [,1] [,2] @@ -118153,6 +123148,11 @@ Error in x[c(NA, 1), 1] <- c(7, 42) : Error in x[c(NA, 1)] <- c(42, 43) : NAs are not allowed in subscripted assignments +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# +#{ x<-1:4; dim(x)<-c(2,2); x[c(NaN,1)]<-c(42, 43); x } +Error in x[c(NaN, 1)] <- c(42, 43) : + NAs are not allowed in subscripted assignments + ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# #{ x<-1:4; dim(x)<-c(2,2); x[c(as.raw(42))]<-c(42,43); x } Error in x[c(as.raw(42))] <- c(42, 43) : invalid subscript type 'raw' @@ -118224,7 +123224,7 @@ Error in x[list(1, 2, 3)] <- c(42, 43) : invalid subscript type 'list' #{ x<-1:4; x[1]<-NULL; x } Error in x[1] <- NULL : replacement has length zero -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther# #{ x<-1:4; x[1]<-c(1,1); x } [1] 1 2 3 4 Warning message: @@ -119551,7 +124551,7 @@ numeric(0) #{ x <- NULL; x[1] <- c(); x; } NULL -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testNullUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testNullUpdate# #{ x <- NULL; x[1] <- c(1,5); x; } [1] 1 Warning message: @@ -119650,7 +124650,7 @@ Error in `[[<-`(`*tmp*`, c(1, 2), value = 5) : #{ x <- NULL; x[c(0,1)] <- c(); x; } NULL -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testNullUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testNullUpdate# #{ x <- NULL; x[c(0,1)] <- c(1,5); x; } [1] 1 Warning message: @@ -119665,7 +124665,7 @@ In x[c(0, 1)] <- c(1, 5) : #{ x <- NULL; x[c(0,2)] <- c(); x; } NULL -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testNullUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testNullUpdate# #{ x <- NULL; x[c(0,2)] <- c(1,5); x; } [1] NA 1 Warning message: @@ -119680,7 +124680,7 @@ In x[c(0, 2)] <- c(1, 5) : #{ x <- NULL; x[c(1,0)] <- c(); x; } NULL -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testNullUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testNullUpdate# #{ x <- NULL; x[c(1,0)] <- c(1,5); x; } [1] 1 Warning message: @@ -121234,6 +126234,10 @@ numeric(0) #{ x<-1; x[NA] } [1] NA +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarDoubleAsVector# +#{ x<-1; x[NaN] } +[1] NA + ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarDoubleAsVector# #{ x<-1; x[TRUE] } [1] 1 @@ -121262,6 +126266,14 @@ numeric(0) #{ x<-3:1; x[3.1] } [1] 1 +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarDoubleIndexOnVector# +#{ x<-3:1; x[NA_real_] } +[1] NA + +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarDoubleIndexOnVector# +#{ x<-3:1; x[NaN] } +[1] NA + ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarDoubleIndexOnVector# #{ x<-c(1,2,3); x[1.1] } [1] 1 @@ -121912,6 +126924,18 @@ integer(0) #{ x<-1L; x[NA] } [1] NA +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarIntAsVector# +#{ x<-1L; x[NA_integer_] } +[1] NA + +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarIntAsVector# +#{ x<-1L; x[NA_real_] } +[1] NA + +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarIntAsVector# +#{ x<-1L; x[NaN] } +[1] NA + ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarIntAsVector# #{ x<-1L; x[TRUE] } [1] 1 @@ -121940,6 +126964,10 @@ integer(0) #{ x<-3:1; x[3L] } [1] 1 +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarIntIndexOnVector# +#{ x<-3:1; x[NA_integer_] } +[1] NA + ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarIntIndexOnVector# #{ x<-c(1,2,3); x[1L] } [1] 1 @@ -122323,7 +127351,7 @@ Error in b[3] <- as.raw(13) : #{ b <- c(1,2) ; z <- b ; b[3L] <- FALSE ; b } [1] 1 2 0 -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarUpdate# #{ b <- c(1,2) ; z <- c(10,11) ; attr(z,"my") <- 4 ; b[2] <- z ; b } [1] 1 10 Warning message: @@ -122877,7 +127905,7 @@ $b attr(,"my") [1] 21 -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testStringUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testStringUpdate# #{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1+2i,3:1,4:6) ; f(c(X=1,a=2),c("X","b",NA),c(TRUE,NA)) } X a b <NA> 1 2 NA 1 @@ -123009,7 +128037,7 @@ $a [1] FALSE -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testStringUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testStringUpdate# #{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(c(X=1,a=2),c("a","X","a","b"),list(3,TRUE,FALSE)) } $X [1] TRUE @@ -123687,7 +128715,7 @@ Error in b[i] <- v : Error in b[[c(NA, 1)]] <- c(2, 10) : attempt to select more than one element in integerOneIndex -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate# #{ b <- 3:4 ; b[c(0,1)] <- c(2,10,11) ; b } [1] 2 4 Warning message: @@ -123813,7 +128841,7 @@ attr(,"my") Error in b[c(FALSE, NA, NA)] <- c("X", "y") : NAs are not allowed in subscripted assignments -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate# #{ b <- c("a","b","c") ; b[c(FALSE,TRUE,TRUE)] <- c("X","y","z") ; b } [1] "a" "X" "y" Warning message: @@ -123873,7 +128901,7 @@ Error in b[c(FALSE, TRUE, NA)] <- c("X", "z") : #{ b <- c(1,2,5) ; x <- as.double(NA) ; attr(x,"my") <- 2 ; b[c(1,NA,2)==2] <- x ; b } [1] 1 2 NA -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate# #{ b <- c(1,2,5) ; x <- c(2,2,-1) ; b[x==2] <- c(10,11,5) ; b } [1] 10 11 5 Warning message: @@ -123928,7 +128956,7 @@ Error in b[c(TRUE, NA, TRUE)] <- list(TRUE, 1 + (0+2i)) : #{ b <- c(1,2,5) ; b[logical()] <- NULL ; b } [1] 1 2 5 -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate# #{ b <- c(1,4,5) ; x <- c(2,2) ; b[x==2] <- c(10,11) ; b } [1] 10 11 10 Warning message: @@ -123959,7 +128987,7 @@ In b[x == 2] <- c(10, 11) : #{ b <- c(TRUE,NA,FALSE) ; b[c(TRUE,FALSE,TRUE,TRUE)] <- c(FALSE,NA,NA) ; b } [1] FALSE NA NA NA -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate# #{ b <- c(TRUE,NA,FALSE) ; b[c(TRUE,TRUE)] <- c(FALSE,NA) ; b } [1] FALSE NA FALSE Warning message: @@ -123980,7 +129008,7 @@ attr(,"my") #{ b <- c(TRUE,NA,FALSE,TRUE) ; b[c(TRUE,FALSE,FALSE)] <- c(FALSE,NA) ; b } [1] FALSE NA FALSE NA -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate# #{ b <- c(TRUE,NA,FALSE,TRUE) ; b[c(TRUE,FALSE,TRUE,FALSE)] <- b ; b } [1] TRUE NA NA TRUE Warning message: @@ -124140,7 +129168,7 @@ $x #{ f <- function(a) { a }; x<-1:5 ; x[x[4]<-2] <- ({x[4]<-100; f(x)[4]}) ; x } [1] 1 100 3 2 5 -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreErrorContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.ImprovedErrorContext# #{ f <- function(b, i, v) { b[[i]] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,NA), 4:5) } Error in `[[<-`(`*tmp*`, i, value = 5:6) : attempt to select more than one element in vectorIndex @@ -124243,7 +129271,7 @@ Error in b[i] <- v : object of type 'closure' is not subsettable #{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3, 1:2, 3:4); f(c(TRUE,FALSE), 2:1, 1:2) } [1] 2 1 -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate# #{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,TRUE,TRUE), 4:6) } [1] 3 4 5 Warning message: @@ -124380,7 +129408,7 @@ Error in b[i] <- v : #{ f <- function(b, i, v) { b[i] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,NA), 4:5) } Error in b[i] <- v : NAs are not allowed in subscripted assignments -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate# #{ f <- function(b, i, v) { b[i] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,TRUE,TRUE), 4:6) } [1] 3 4 5 Warning message: @@ -124610,7 +129638,7 @@ Error in b[i] <- v : only 0's may be mixed with negative subscripts #{ f <- function(b,i,v) { b[[i]] <- v ; b } ; f(1:2,"hi",3L) ; f(1:2,c(2),10) ; f(1:2, -1, 10) } [1] 1 10 -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate# #{ f <- function(b,i,v) { b[b] <- b ; b } ; f(c(TRUE,FALSE,FALSE,TRUE)) ; f(1:3) } [1] 1 2 3 Warning message: @@ -124977,7 +130005,7 @@ attr(,"my") #{ x <- c(1L,2L,3L,4L) ; x[c(TRUE,FALSE)] <- 5:6 ; x } [1] 5 2 6 4 -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate# #{ x <- c(1L,2L,3L,4L) ; x[c(TRUE,FALSE)] <- rev(x) ; x } [1] 4 2 3 4 Warning message: @@ -125069,7 +130097,7 @@ $b [1] "b" -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate# #{ x <- list(1,0) ; attr(x,"my") <- 20 ; x[c(TRUE,FALSE)] <- c(11,12) ; x } [[1]] [1] 11 @@ -125083,7 +130111,7 @@ Warning message: In x[c(TRUE, FALSE)] <- c(11, 12) : number of items to replace is not a multiple of replacement length -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate# #{ x <- list(1,0) ; x[as.logical(x)] <- c(10,11); x } [[1]] [1] 10 @@ -125095,7 +130123,7 @@ Warning message: In x[as.logical(x)] <- c(10, 11) : number of items to replace is not a multiple of replacement length -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate# #{ x <- list(1,0) ; x[c(TRUE,FALSE)] <- x[2:1] ; x } [[1]] [1] 0 @@ -125143,7 +130171,7 @@ In x[c(TRUE, FALSE)] <- x[2:1] : [1] 0 -##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate# #{ x <- list(1,2) ; attr(x,"my") <- 10; x[c(TRUE,TRUE)] <- c(10,11,12); x } [[1]] [1] 10 @@ -125388,6 +130416,30 @@ a b c d e #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels9.R") } [1] TRUE FALSE +##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests# +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/sharing1.R") } +[1] 42 7 + +##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests# +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/sharing2.R") } +[1] "object 'x' not found" + +##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests# +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/sharing3.R") } +[1] 42 7 + +##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests# +#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/sharing4.R") } +[1] 24 42 + +##com.oracle.truffle.r.test.library.fastr.TestInterop.testChannelConnection# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { v <- .fastr.interop.import('_fastr_channel0'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); writeLines('hi there', zz); close(zz); NULL } +NULL + +##com.oracle.truffle.r.test.library.fastr.TestInterop.testChannelConnection# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('Hello, World!', 'second line') } else { v <- .fastr.interop.import('_fastr_channel0'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); res <- readLines(zz); close(zz); res } +[1] "Hello, World!" "second line" + ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEval# #if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { .fastr.interop.eval('application/x-r', '1') } [1] 1 @@ -125430,6 +130482,11 @@ a b c d e ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropExport# #if (length(grep("FastR", R.Version()$version.string)) != 1) { invisible() } else { .fastr.interop.export('foo', new.env()) } +##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('intValue', 'longValue', 'charValue', 'shortValue', 'booleanValue', 'stringValue') } else { v <- .fastr.interop.import('testPOJO'); names(v) } +[1] "intValue" "longValue" "charValue" "shortValue" "booleanValue" +[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) } $intValue @@ -125471,6 +130528,1180 @@ attr(,"is.truffle.object") 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") } +[1] "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString" + +##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$allTypesStaticMethod(TRUE,127,"a",32767,2147483647,9223372036854775807,1.7976931348623157E308,3.4028235E38,"testString") } +[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]; } +[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]]; } +[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] } +[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]] } +[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] } +[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] } +[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]] } +[1] 123 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1234 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[[1]] <- 1234L; t$fieldIntArray[[1]] } +[1] 1234 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1234 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[1,2] <- 1234L; t$int2DimArray[1,2] } +[1] 1234 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 12345 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[[1,2]] <- 12345L; t$int2DimArray[[1,2]] } +[1] 12345 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[1,2] } +[1] 2 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[[1,2]] } +[1] 2 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStringArray[1] <- NULL; t$fieldStringArray[1] } +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] } +[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]] } +[1] 1 2 3 +attr(,"is.truffle.object") +[1] TRUE + +##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) } +[1] "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.byte' } else { class(c(.fastr.interop.toByte(123))) } +[1] "interopt.byte" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { class(c(.fastr.interop.toByte(123), .fastr.interop.toByte(234))) } +[1] "list" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { class(c(.fastr.interop.toByte(123), 1)) } +[1] "list" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { class(c(1, .fastr.interop.toByte(123))) } +[1] "list" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); class(c(1, t)) } +[1] "list" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); class(c(t, 1)) } +[1] "list" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t1 <- .fastr.interop.new(tc); class(c(t, t1)) } +[1] "list" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'truffle.object' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); class(c(t)) } +[1] "truffle.object" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a string" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticStringObject } +[1] "a string" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a string" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStringObject } +[1] "a string" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldChar } +[1] "a" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldCharObject } +[1] "a" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticChar } +[1] "a" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticCharObject } +[1] "a" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldDouble } +[1] 1.797693e+308 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldDoubleObject } +[1] 1.797693e+308 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticDouble } +[1] 1.797693e+308 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticDoubleObject } +[1] 1.797693e+308 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldByte } +[1] 127 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldByteObject } +[1] 127 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticByte } +[1] 127 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticByteObject } +[1] 127 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldInteger } +[1] 2147483647 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntegerObject } +[1] 2147483647 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticInteger } +[1] 2147483647 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticIntegerObject } +[1] 2147483647 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldFloat } +[1] 3.402823e+38 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldFloatObject } +[1] 3.402823e+38 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticFloat } +[1] 3.402823e+38 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticFloatObject } +[1] 3.402823e+38 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldShort } +[1] 32767 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldShortObject } +[1] 32767 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticShort } +[1] 32767 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticShortObject } +[1] 32767 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldLong } +[1] 9.223372e+18 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldLongObject } +[1] 9.223372e+18 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticLong } +[1] 9.223372e+18 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticLongObject } +[1] 9.223372e+18 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldNullObject } +NULL + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticNullObject } +NULL + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { NaN } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticNaN } +[1] NaN + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { NaN } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticNaNObject } +[1] NaN + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldBoolean } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldBooleanObject } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticBoolean } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticBooleanObject } +[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 } +[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 } +[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 } +[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 } +[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 } +[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 } +[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 } +[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 } +[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 } +[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 } +[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 } +[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 } +[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 } +[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 } +[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 } +[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 } +[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 } +[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 } +[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) } +[1] "character" + +##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$fieldStaticStringArray); typeof(v) } +[1] "character" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "double" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticDoubleArray); typeof(v) } +[1] "double" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "double" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticFloatArray); typeof(v) } +[1] "double" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "double" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticLongArray); typeof(v) } +[1] "double" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "double" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$objectDoubleArray); typeof(v) } +[1] "double" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "integer" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticByteArray); typeof(v) } +[1] "integer" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "integer" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticIntArray); typeof(v) } +[1] "integer" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "integer" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticShortArray); typeof(v) } +[1] "integer" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "integer" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$objectIntArray); typeof(v) } +[1] "integer" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "logical" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticBooleanArray); typeof(v) } +[1] "logical" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticBooleanArray); is.vector(v) } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticByteArray); is.vector(v) } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticCharArray); is.vector(v) } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticDoubleArray); is.vector(v) } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticFloatArray); is.vector(v) } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticIntArray); is.vector(v) } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticLongArray); is.vector(v) } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticShortArray); is.vector(v) } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticStringArray); is.vector(v) } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$hasNullIntArray); is.list(v) } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$mixedTypesArray); is.list(v) } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$objectArray); is.list(v) } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$objectDoubleArray); is.vector(v) } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$objectIntArray); is.vector(v) } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { list(1) } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[1] } +[[1]] +[1] 1 + + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { list(3) } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[3] } +[[1]] +[1] 3 + + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { list(NULL) } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[2] } +[[1]] +NULL + + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a string" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticStringObject() } +[1] "a string" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a string" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStringObject() } +[1] "a string" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodChar() } +[1] "a" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodCharObject() } +[1] "a" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticChar() } +[1] "a" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticCharObject() } +[1] "a" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodDouble() } +[1] 1.797693e+308 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodDoubleObject() } +[1] 1.797693e+308 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticDouble() } +[1] 1.797693e+308 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticDoubleObject() } +[1] 1.797693e+308 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodByte() } +[1] 127 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodByteObject() } +[1] 127 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticByte() } +[1] 127 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticByteObject() } +[1] 127 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodInteger() } +[1] 2147483647 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodIntegerObject() } +[1] 2147483647 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticInteger() } +[1] 2147483647 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticIntegerObject() } +[1] 2147483647 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodFloat() } +[1] 3.402823e+38 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodFloatObject() } +[1] 3.402823e+38 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticFloat() } +[1] 3.402823e+38 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticFloatObject() } +[1] 3.402823e+38 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodShort() } +[1] 32767 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodShortObject() } +[1] 32767 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticShort() } +[1] 32767 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticShortObject() } +[1] 32767 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodLong() } +[1] 9.223372e+18 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodLongObject() } +[1] 9.223372e+18 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticLong() } +[1] 9.223372e+18 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticLongObject() } +[1] 9.223372e+18 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodReturnsNull() } +NULL + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticReturnsNull() } +NULL + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodBoolean() } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodBooleanObject() } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticBoolean() } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticBooleanObject() } +[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() } +[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() } +[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() } +[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() } +[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) } +NULL + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForJavaObject# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClass'); names(tc$staticField) } +NULL + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForJavaObject# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClass'); names(tc$staticMethod) } +NULL + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForJavaObject# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClassNoMembers'); t <- .fastr.interop.new(tc); names(t) } +NULL + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForJavaObject# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClassNoPublicMembers'); t <- .fastr.interop.new(tc); names(t) } +NULL + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForJavaObject# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('field', 'method', 'staticField', 'staticMethod') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClass'); t <- .fastr.interop.new(tc); sort(names(t)) } +[1] "field" "method" "staticField" "staticMethod" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForJavaObject# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('one', 'two') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClassMap'); t <- .fastr.interop.new(tc); sort(names(t$m())) } +[1] "one" "two" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForJavaObject# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('staticField', 'staticMethod') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClass'); sort(names(tc)) } +[1] "staticField" "staticMethod" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { tc <- .fastr.java.class('java.lang.Character'); t <- .fastr.interop.new(tc, .fastr.interop.toChar(97)); t } +[1] "a" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'abc' } else { tc <- .fastr.java.class('java.lang.String'); t <- .fastr.interop.new(tc, 'abc'); t } +[1] "abc" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'truffle.object' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNullClass'); t <- .fastr.interop.new(tc, NULL); class(t) } +[1] "truffle.object" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('java.lang.Byte'); t <- .fastr.interop.new(tc, .fastr.interop.toByte(1)); t } +[1] 1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('java.lang.Integer'); t <- .fastr.interop.new(tc, 1L); t } +[1] 1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('java.lang.Long'); t <- .fastr.interop.new(tc, .fastr.interop.toLong(1)); t } +[1] 1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('java.lang.Short'); t <- .fastr.interop.new(tc, .fastr.interop.toShort(1)); t } +[1] 1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.1 } else { tc <- .fastr.java.class('java.lang.Double'); t <- .fastr.interop.new(tc, 1.1); t } +[1] 1.1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.1 } else { tc <- .fastr.java.class('java.lang.Float'); t <- .fastr.interop.new(tc, .fastr.interop.toFloat(1.1)); t } +[1] 1.1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('java.lang.Boolean'); t <- .fastr.interop.new(tc, TRUE); t } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNonPrimitiveParameter# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$equals(t) } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameters# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodAcceptsOnlyNull(NULL) } +NULL + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameters#Ignored.Unimplemented# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { java.lang.Long } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isNull(1) } +Error: object 'java.lang.Long' not found + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameters#Ignored.Unimplemented# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { java.lang.String } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isNull('string') } +Error: object 'java.lang.String' not found + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#Ignored.Unimplemented# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { boolean } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isOverloaded(TRUE) } +Error: object 'boolean' not found + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#Ignored.Unimplemented# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { java.lang.String } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isOverloaded('string') } +Error: object 'java.lang.String' not found + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); to <- .fastr.interop.new(tc); a <- .fastr.java.toArray(c(to, to)); .fastr.java.isArray(a) } +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); to <- .fastr.interop.new(tc); a <- .fastr.java.toArray(to); .fastr.java.isArray(a) } +[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; } +[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; } +[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; } +[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; } +[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; } +[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; } +[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; } +[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; } +[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; } +[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; } +[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; } +[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; } +[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; } +[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; } +[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; } +[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; } +[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; } +[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; } +[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); } +[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; } +[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; } +[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; } +[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; } +[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; } +[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); } +[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); } +[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; } +[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; } +[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; } +[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") +[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") +[1] TRUE + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.byte' } else { v <- .fastr.interop.toByte(1.1); class(v); } +[1] "interopt.byte" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.byte' } else { v <- .fastr.interop.toByte(1.1); typeof(v); } +[1] "interopt.byte" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { -1 } else { v <- .fastr.interop.toByte(1.7976931348623157E308); v; } +[1] -1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { -1 } else { v <- .fastr.interop.toByte(2147483647); v; } +[1] -1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { -128 } else { v <- .fastr.interop.toByte(-128); v; } +[1] -128 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toByte(-2147483648); v; } +[1] 0 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toByte(4.9E-324); v; } +[1] 0 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toByte(1.1); v; } +[1] 1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toByte(1L); v; } +[1] 1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toByte(as.raw(1)); v; } +[1] 1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { v <- .fastr.interop.toByte(127); v; } +[1] 127 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { v <- .fastr.interop.toChar('a'); v; } +[1] "a" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { v <- .fastr.interop.toChar(97.1); v; } +[1] "a" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { v <- .fastr.interop.toChar(97L); v; } +[1] "a" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'b' } else { v <- .fastr.interop.toChar('abc', 1); v; } +[1] "b" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'b' } else { v <- .fastr.interop.toChar('abc', 1.1); v; } +[1] "b" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.char' } else { v <- .fastr.interop.toChar(97.1); class(v); } +[1] "interopt.char" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.char' } else { v <- .fastr.interop.toChar(97.1); typeof(v); } +[1] "interopt.char" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.char' } else { v <- .fastr.interop.toChar(97L); class(v); } +[1] "interopt.char" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.char' } else { v <- .fastr.interop.toChar(97L); typeof(v); } +[1] "interopt.char" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('Error in .fastr.interop.toChar(97.1, 1) : ', '<<<NEWLINE>>>', ' pos argument not allowed with a numeric value', '<<<NEWLINE>>>') } else { v <- .fastr.interop.toChar(97.1, 1); v; } +Error in .fastr.interop.toChar(97.1, 1) : + pos argument not allowed with a numeric value + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('Error in .fastr.interop.toChar(97L, 1) : ','<<<NEWLINE>>>',' pos argument not allowed with a numeric value', '<<<NEWLINE>>>') } else { v <- .fastr.interop.toChar(97L, 1); v; } +Error in .fastr.interop.toChar(97L, 1) : + pos argument not allowed with a numeric value + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.float' } else { v <- .fastr.interop.toFloat(1.1); class(v); } +[1] "interopt.float" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.float' } else { v <- .fastr.interop.toFloat(1.1); typeof(v); } +[1] "interopt.float" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.float' } else { v <- .fastr.interop.toFloat(1L); class(v); } +[1] "interopt.float" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.float' } else { v <- .fastr.interop.toFloat(1L); typeof(v); } +[1] "interopt.float" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0.0 } else { v <- .fastr.interop.toFloat(4.9E-324); v; } +[1] 0 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toFloat(1L); v; } +[1] 1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toFloat(as.raw(1)); v; } +[1] 1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.1 } else { v <- .fastr.interop.toFloat(1.1); v; } +[1] 1.1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.401298464324817E-45 } else { v <- .fastr.interop.toFloat(1.4E-45); v; } +[1] 1.401298e-45 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { v <- .fastr.interop.toFloat(3.4028235E38); v; } +[1] 3.402823e+38 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { Inf } else { v <- .fastr.interop.toFloat(1.7976931348623157E308); v; } +[1] Inf + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.long' } else { v <- .fastr.interop.toLong(1.1); class(v); } +[1] "interopt.long" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.long' } else { v <- .fastr.interop.toLong(1.1); typeof(v); } +[1] "interopt.long" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.long' } else { v <- .fastr.interop.toLong(1L); class(v); } +[1] "interopt.long" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.long' } else { v <- .fastr.interop.toLong(1L); typeof(v); } +[1] "interopt.long" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { -2147483648 } else { v <- .fastr.interop.toLong(-2147483648); v; } +[1] -2147483648 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toLong(4.9E-324); v; } +[1] 0 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toLong(1.1); v; } +[1] 1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toLong(1L); v; } +[1] 1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toLong(as.raw(1)); v; } +[1] 1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { v <- .fastr.interop.toLong(2147483647); v; } +[1] 2147483647 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { v <- .fastr.interop.toLong(1.7976931348623157E308); v; } +[1] 9.223372e+18 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.short' } else { v <- .fastr.interop.toShort(1.1); class(v); } +[1] "interopt.short" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.short' } else { v <- .fastr.interop.toShort(1.1); typeof(v); } +[1] "interopt.short" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.short' } else { v <- .fastr.interop.toShort(1L); class(v); } +[1] "interopt.short" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.short' } else { v <- .fastr.interop.toShort(1L); typeof(v); } +[1] "interopt.short" + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { -1 } else { v <- .fastr.interop.toShort(1.7976931348623157E308); v; } +[1] -1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { -1 } else { v <- .fastr.interop.toShort(2147483647); v; } +[1] -1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { -32768 } else { v <- .fastr.interop.toShort(-32768); v; } +[1] -32768 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toShort(-2147483648); v; } +[1] 0 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toShort(4.9E-324); v; } +[1] 0 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toShort(1.1); v; } +[1] 1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toShort(1L); v; } +[1] 1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toShort(as.raw(1)); v; } +[1] 1 + +##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort# +#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { v <- .fastr.interop.toShort(32767); v; } +[1] 32767 + ##com.oracle.truffle.r.test.library.fastr.TestStateTrans.testTransitions# #if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { { f<-function(x) .fastr.refcountinfo(x); f(c(1,2)) } } [1] 1 @@ -125499,22 +131730,6 @@ attr(,"is.truffle.object") #if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { { x<-rep(1, 100); xi1<-.fastr.identity(x); f<-function(x) { y<-x; y }; f(x); x[1]<-7; xi2<-.fastr.identity(x); xi1 == xi2 } } [1] TRUE -##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits# -#{ library(grid); 3 * (unit(1, 'mm')); } -[1] 3*1mm - -##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits# -#{ library(grid); grid:::unit.list(3 * unit(1, 'mm')); } -[1] 3*1mm - -##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits# -#{ library(grid); unit.c(unit(1,'mm'), 42*unit(1,'mm')); } -[1] 1mm 42*1mm - -##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits# -#{ library(grid); unit.c(unit(1,'mm'), unit(1,'mm')) } -[1] 1mm 1mm - ##com.oracle.truffle.r.test.library.methods.TestSubstituteDirect.basicTests# #a<-substituteDirect(quote(x+1), NA); a Error in substituteDirect(quote(x + 1), NA) : @@ -131644,7 +137859,7 @@ In qwilcox(log(c(0, 4.2e-79, 0.1, 0.5, 0.7, 1 - 4.2e-79, 1)), 4, : [1] 0.000000 0.000000 0.000000 1.333333 6.000000 5.666667 5.000000 0.000000 [9] 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -##com.oracle.truffle.r.test.library.stats.TestExternal_BinDist.testBinDistWrongArgs#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.stats.TestExternal_BinDist.testBinDistWrongArgs# #.Call(stats:::C_BinDist, 0, 0, 'string', 3, 5) [1] 0 0 0 0 0 0 0 0 0 0 Warning message: @@ -131820,7 +138035,7 @@ In qgamma(10, 1) : NaNs produced #set.seed(42); rbinom('10', 10, 0.5) [1] 7 7 4 7 6 5 6 3 6 6 -##com.oracle.truffle.r.test.library.stats.TestExternal_rbinom.testRbinom#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.stats.TestExternal_rbinom.testRbinom# #set.seed(42); rbinom('aa', 10, 0.5) Error in rbinom("aa", 10, 0.5) : invalid arguments In addition: Warning message: @@ -134740,7 +140955,7 @@ Error in rwilcox(30, c(NA, 0, NaN, 1/0, -1/0), c(NaN, NaN, NA, 0, 1/0, : #length(runif(c(1,2,3))) [1] 3 -##com.oracle.truffle.r.test.library.stats.TestRandGenerationFunctions.testFunctions2Infrastructure#Output.IgnoreWarningContext# +##com.oracle.truffle.r.test.library.stats.TestRandGenerationFunctions.testFunctions2Infrastructure# #runif('hello') Error in runif("hello") : invalid arguments In addition: Warning message: @@ -134810,7 +141025,49 @@ In rhyper(1, NA, 5, 20) : NAs produced #set.seed(3); rhyper(3, 10, 79e70, 2) [1] 0 0 0 -##com.oracle.truffle.r.test.library.stats.TestRandGenerationFunctions.testRmultinom#Output.IgnoreErrorContext#Output.IgnoreErrorMessage# +##com.oracle.truffle.r.test.library.stats.TestRandGenerationFunctions.testGenerators# +#for(gen in c("Buggy Kinderman-Ramage", "Ahrens-Dieter", "Box-Muller", "Inversion", "Kinderman-Ramage", "default")) { print(paste0(gen, ":")); RNGkind(NULL,gen); set.seed(42); print(rnorm(30)); } +[1] "Buggy Kinderman-Ramage:" + [1] -0.79604712 1.28771872 0.71745084 -0.42255829 0.56567165 1.65777846 + [7] -0.55131328 1.00482417 -0.24735845 0.24860615 -0.36036694 -1.73747216 +[13] -0.25369717 -1.04076998 2.23551204 -0.28116912 -0.46380894 -0.16281811 +[19] 1.16178557 -1.20815956 0.57057609 2.45914868 0.33370144 0.29920774 +[25] 0.05462671 -1.79697222 -0.61127365 -0.12708318 -1.36417253 -0.92312656 +[1] "Ahrens-Dieter:" + [1] -1.273084700 -1.414657032 0.739312189 -0.893074355 -0.321064732 + [6] -0.008679202 -0.584610918 0.302830939 -0.361476229 -0.493404872 +[11] 1.546579146 -0.553905239 -1.531588211 -0.112289664 -1.217388818 +[16] 0.313559035 -2.138347829 1.148211398 -1.226981451 1.478797153 +[21] -0.915508892 -0.587726941 -0.825282001 1.137582651 -0.438588414 +[26] 2.420172264 2.565920821 1.405014135 0.054642602 -1.756587679 +[1] "Box-Muller:" + [1] 0.31010081 -0.18390356 -0.13723045 0.59392645 -0.72021551 -0.89029361 + [7] -0.16854514 -1.99536938 -0.46122133 -0.69728478 -0.78362342 0.21309613 +[13] 1.51492034 -0.65927181 -0.34191267 0.08255685 2.05016803 -0.28224116 +[19] -1.06305839 0.16839189 1.63711374 -1.12720712 0.33027271 -0.02308900 +[25] 1.00206928 0.57104929 -0.34322783 0.28320445 -0.56561519 0.19576159 +[1] "Inversion:" + [1] 1.37095845 -0.56469817 0.36312841 0.63286260 0.40426832 -0.10612452 + [7] 1.51152200 -0.09465904 2.01842371 -0.06271410 1.30486965 2.28664539 +[13] -1.38886070 -0.27878877 -0.13332134 0.63595040 -0.28425292 -2.65645542 +[19] -2.44046693 1.32011335 -0.30663859 -1.78130843 -0.17191736 1.21467470 +[25] 1.89519346 -0.43046913 -0.25726938 -1.76316309 0.46009735 -0.63999488 +[1] "Kinderman-Ramage:" + [1] -0.79604712 1.28771872 0.71745084 -0.42255829 0.56567165 1.65777846 + [7] -0.55131328 1.00482417 -0.24735845 0.21355380 1.43016945 0.27516802 +[13] -0.36036694 -1.73747216 -0.25369717 -1.04076998 2.23551204 -0.28116912 +[19] -0.46380894 -0.16281811 1.16178557 -1.20815956 0.57057609 2.45914868 +[25] 0.33370144 0.29920774 0.05462671 -1.79697222 -0.61127365 -0.12708318 +[1] "default:" + [1] 1.37095845 -0.56469817 0.36312841 0.63286260 0.40426832 -0.10612452 + [7] 1.51152200 -0.09465904 2.01842371 -0.06271410 1.30486965 2.28664539 +[13] -1.38886070 -0.27878877 -0.13332134 0.63595040 -0.28425292 -2.65645542 +[19] -2.44046693 1.32011335 -0.30663859 -1.78130843 -0.17191736 1.21467470 +[25] 1.89519346 -0.43046913 -0.25726938 -1.76316309 0.46009735 -0.63999488 +Warning message: +In RNGkind(NULL, gen) : buggy version of Kinderman-Ramage generator used + +##com.oracle.truffle.r.test.library.stats.TestRandGenerationFunctions.testRmultinom# #rmultinom('string', 1, 0.15) Error in rmultinom("string", 1, 0.15) : invalid first argument 'n' In addition: Warning message: @@ -138224,6 +144481,63 @@ x + x ~ y + log(y) #update.formula(x ~ y, ~ . + x2) x ~ y + x2 +##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testConditionalBreakpoint# +#fun <- function(x) { cat('x='); cat(x); cat('\n') }; trace(fun, quote(if (x > 10) browser())); fun(10)<<<NEWLINE>>>; fun(11)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>> +[1] "fun" +Tracing fun(10) on entry +x=10 +Error: unexpected ';' in ";" + +##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testContinue# +#fun0 <- function() { print('fun0') }; fun1 <- function() { print('enter fun1'); fun0(); print('exit fun1') }; fun2 <- function() { print('enter fun2'); fun1(); print('exit fun2') }; debug(fun2); fun2()<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>s<<<NEWLINE>>>n<<<NEWLINE>>><<<NEWLINE>>>s<<<NEWLINE>>>c<<<NEWLINE>>>c<<<NEWLINE>>>c<<<NEWLINE>>> +debugging in: fun2() +debug at #1: { + print("enter fun2") + fun1() + print("exit fun2") +} +debug at #1: print("enter fun2") +[1] "enter fun2" +debug at #1: fun1() +debugging in: fun1() +debug at #1: { + print("enter fun1") + fun0() + print("exit fun1") +} +debug at #1: print("enter fun1") +[1] "enter fun1" +debug at #1: fun0() +debugging in: fun0() +debug at #1: { + print("fun0") +} +[1] "fun0" +debug at #1: print("exit fun1") +[1] "exit fun1" +debug at #1: print("exit fun2") +[1] "exit fun2" +exiting from: fun2() + +##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testDebugOnce# +#fun0 <- function() { print('fun0') }; debugonce(fun0); fun0()<<<NEWLINE>>>c<<<NEWLINE>>> +debugging in: fun0() +debug at #1: { + print("fun0") +} +[1] "fun0" + +##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testDebugOnce# +#fun0 <- function() { print('fun0') }; fun1 <- function() { print('en'); fun0(); fun0(); print('ex') }; debugonce(fun0); fun1()<<<NEWLINE>>>c<<<NEWLINE>>> +[1] "en" +debugging in: fun0() +debug at #1: { + print("fun0") +} +[1] "fun0" +[1] "fun0" +[1] "ex" + ##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testInvalidName# #f <- function(x) {<<<NEWLINE>>> `123t` <- x + 1<<<NEWLINE>>> print(`123t`)<<<NEWLINE>>> `123t`}<<<NEWLINE>>>debug(f)<<<NEWLINE>>>f(5)<<<NEWLINE>>>x<<<NEWLINE>>>n<<<NEWLINE>>>n<<<NEWLINE>>>`123t`<<<NEWLINE>>>n<<<NEWLINE>>>n debugging in: f(5) @@ -138241,6 +144555,120 @@ debug at #4: `123t` exiting from: f(5) [1] 6 +##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testLoop# +#fun <- function(x) { for(i in seq(x)) cat(i); cat(5) }; debug(fun); fun(3)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>> +debugging in: fun(3) +debug at #1: { + for (i in seq(x)) cat(i) + cat(5) +} +debug at #1: for (i in seq(x)) cat(i) +debug at #1: cat(i) +1debug at #1: cat(i) +2debug at #1: cat(i) +3debug at #1: cat(5) +5exiting from: fun(3) + +##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testLoop# +#fun <- function(x) { for(i in seq(x)) { cat(i) }; cat(5) }; debug(fun); fun(3)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>> +debugging in: fun(3) +debug at #1: { + for (i in seq(x)) { + cat(i) + } + cat(5) +} +debug at #1: for (i in seq(x)) { + cat(i) +} +debug at #1: cat(i) +1debug at #1: cat(i) +2debug at #1: cat(i) +3debug at #1: cat(5) +5exiting from: fun(3) + +##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testLoop# +#fun <- function(x) { for(i in seq(x)) { cat(i) }; cat(5) }; debug(fun); fun(3)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>f<<<NEWLINE>>><<<NEWLINE>>> +debugging in: fun(3) +debug at #1: { + for (i in seq(x)) { + cat(i) + } + cat(5) +} +debug at #1: for (i in seq(x)) { + cat(i) +} +debug at #1: cat(i) +1debug at #1: cat(i) +23debug at #1: cat(5) +5exiting from: fun(3) + +##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testLoop# +#fun <- function(x) { for(j in seq(2)) for(i in seq(x)) cat(i); cat(5) }; debug(fun); fun(3)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>> +debugging in: fun(3) +debug at #1: { + for (j in seq(2)) for (i in seq(x)) cat(i) + cat(5) +} +debug at #1: for (j in seq(2)) for (i in seq(x)) cat(i) +debug at #1: for (i in seq(x)) cat(i) +debug at #1: cat(i) +1debug at #1: cat(i) +2debug at #1: cat(i) +3debug at #1: for (i in seq(x)) cat(i) +debug at #1: cat(i) +1debug at #1: cat(i) +2debug at #1: cat(i) +3debug at #1: cat(5) +5exiting from: fun(3) + +##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testLoop# +#fun <- function(x) { for(j in seq(2)) for(i in seq(x)) cat(i); cat(5) }; debug(fun); fun(3)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>f<<<NEWLINE>>>f<<<NEWLINE>>><<<NEWLINE>>> +debugging in: fun(3) +debug at #1: { + for (j in seq(2)) for (i in seq(x)) cat(i) + cat(5) +} +debug at #1: for (j in seq(2)) for (i in seq(x)) cat(i) +debug at #1: for (i in seq(x)) cat(i) +debug at #1: cat(i) +123debug at #1: for (i in seq(x)) cat(i) +123debug at #1: cat(5) +5exiting from: fun(3) + +##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testNestedDebugging#Output.IgnoreDebugPath# +#foo <- function(rCode) { eval(parse(text=rCode)); print('foo done') }; debug(foo); foo("bar <- function() { print('bar') }; debug(bar); bar()")<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>> +debugging in: foo("bar <- function() { print('bar') }; debug(bar); bar()") +debug at #1: { + eval(parse(text = rCode)) + print("foo done") +} +debug at #1: eval(parse(text = rCode)) +debugging in: bar() +debug at <text>#1: { + print("bar") +} +debug at <text>#1: print("bar") +[1] "bar" +exiting from: bar() +debug at #1: print("foo done") +[1] "foo done" +exiting from: foo("bar <- function() { print('bar') }; debug(bar); bar()") + +##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testNestedDebugging#Output.IgnoreDebugPath# +#foo <- function(rCode) { eval(parse(text=rCode)); print('foo done') }; debug(foo); foo("bar <- function() { print('bar') }; debug(bar); bar()")<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>Q<<<NEWLINE>>> +debugging in: foo("bar <- function() { print('bar') }; debug(bar); bar()") +debug at #1: { + eval(parse(text = rCode)) + print("foo done") +} +debug at #1: eval(parse(text = rCode)) +debugging in: bar() +debug at <text>#1: { + print("bar") +} + ##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testNoBracket# #f <- function(x) print(x)<<<NEWLINE>>>debug(f)<<<NEWLINE>>>f(5)<<<NEWLINE>>>x<<<NEWLINE>>>n<<<NEWLINE>>> debugging in: f(5) @@ -138249,6 +144677,24 @@ debug: print(x) [1] 5 exiting from: f(5) +##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testPromise#Ignored.ImplementationError# +#fun <- function(x) { cat({ cat(x); cat('<<<NEWLINE>>>') }) }; debug(fun); fun(3)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>> +debugging in: fun(3) +debug at #1: { + cat({ + cat(x) + cat("\n") + }) +} +debug at #1: cat({ + cat(x) + cat("\n") +}) +debug at #1: cat(x) +3debug at #1: cat("\n") + +exiting from: fun(3) + ##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testSimple# #f <- function(x) {<<<NEWLINE>>> t <- x + 1<<<NEWLINE>>> print(t)<<<NEWLINE>>> t}<<<NEWLINE>>>debug(f)<<<NEWLINE>>>f(5)<<<NEWLINE>>>x<<<NEWLINE>>>n<<<NEWLINE>>>n<<<NEWLINE>>>t<<<NEWLINE>>>n<<<NEWLINE>>>n debugging in: f(5) @@ -138266,6 +144712,74 @@ debug at #4: t exiting from: f(5) [1] 6 +##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testStepInto# +#bar <- function(x) { cat(x); cat('\n') }; foo <- function(x) { cat('foo entry\n'); bar(x); cat('foo exit\n') }; debug(foo); foo(3)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>s<<<NEWLINE>>>n<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>> +debugging in: foo(3) +debug at #1: { + cat("foo entry\n") + bar(x) + cat("foo exit\n") +} +debug at #1: cat("foo entry\n") +foo entry +debug at #1: bar(x) +debugging in: bar(x) +debug at #1: { + cat(x) + cat("\n") +} +debug at #1: cat(x) +3debug at #1: cat("\n") + +debug at #1: cat("foo exit\n") +foo exit +exiting from: foo(3) + +##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testStepInto# +#bar <- function(x) { cat(x); cat('\n') }; foo <- function(x) { cat('foo entry\n'); bar(x); cat('foo exit\n') }; debug(foo); foo(3)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>s<<<NEWLINE>>>n<<<NEWLINE>>>Q<<<NEWLINE>>> +debugging in: foo(3) +debug at #1: { + cat("foo entry\n") + bar(x) + cat("foo exit\n") +} +debug at #1: cat("foo entry\n") +foo entry +debug at #1: bar(x) +debugging in: bar(x) +debug at #1: { + cat(x) + cat("\n") +} +debug at #1: cat(x) + +##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testStepInto# +#bar <- function(x) { for(i in seq(x)) print(x) }; foo <- function(x) { cat('foo entry\n'); bar(x); cat('foo exit\n') }; debug(foo); foo(5)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>s<<<NEWLINE>>>n<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>f<<<NEWLINE>>><<<NEWLINE>>> +debugging in: foo(5) +debug at #1: { + cat("foo entry\n") + bar(x) + cat("foo exit\n") +} +debug at #1: cat("foo entry\n") +foo entry +debug at #1: bar(x) +debugging in: bar(x) +debug at #1: { + for (i in seq(x)) print(x) +} +debug at #1: for (i in seq(x)) print(x) +debug at #1: print(x) +[1] 5 +debug at #1: print(x) +[1] 5 +[1] 5 +[1] 5 +[1] 5 +debug at #1: cat("foo exit\n") +foo exit +exiting from: foo(5) + ##com.oracle.truffle.r.test.library.utils.TestTrace.testCondTrace# #f <- function(x) {}; (if (exists('.fastr.trace')) .fastr.trace else trace)(f, tracer=quote(if (x == 3 || x == 7) print(x))); g <- function() for (i in 1:10) f(i); g() [1] "f" @@ -138606,7 +145120,7 @@ Levels: 2147483648L #typeof(type.convert('2147483648L')) [1] "integer" -##com.oracle.truffle.r.test.library.utils.TestTypeConvert.testFirstTypeMustBeOfModeTest#Ignored.Unimplemented# +##com.oracle.truffle.r.test.library.utils.TestTypeConvert.testFirstTypeMustBeOfModeTest# #type.convert('NA', 1) Error in type.convert("NA", 1) : invalid 'na.strings' argument @@ -138829,6 +145343,85 @@ see '?methods' for accessing help and source code #0xa.p2 [1] 40 +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols# +#``(1) +Error: attempt to use zero-length variable name + +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols# +#as.symbol('')) +Error: unexpected ')' in "as.symbol(''))" + +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols# +#e <- quote(b(f=1,foo)); names(e) <- c('','',''); e +b(1, foo) + +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols# +#e <- quote(b(f=1,foo)); names(e) <- c('','f',''); e +b(f = 1, foo) + +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#Output.IgnoreErrorMessage# +#e <- quote(x <- 1); e[[2]] <- as.symbol(''); +Error in as.symbol("") : attempt to use zero-length variable name + +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#Output.IgnoreErrorMessage# +#f <- function(){ function('') cat(asdf=1) } +Error: unexpected string constant in "f <- function(){ function(''" + +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols# +#f <- function(){ function() cat(``=1) } +Error: attempt to use zero-length variable name + +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols# +#f <- function(){ function() cat(asdf=1) } + +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols# +#f <- function(){ function(``) cat(asdf=1) } +Error: attempt to use zero-length variable name + +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols# +#f <- function(){ function(``=1) 1 } +Error: attempt to use zero-length variable name + +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols# +#f <- function(){ function(``=1) cat(``=1) } +Error: attempt to use zero-length variable name + +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols# +#names(e) +Error: object 'e' not found + +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols# +#quote(``(1)) +Error: attempt to use zero-length variable name + +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols# +#quote(``:::a) +Error: attempt to use zero-length variable name + +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols# +#quote(a$'') +a$"" + +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols# +#quote(a$``) +Error: attempt to use zero-length variable name + +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols# +#quote(a$b) +a$b + +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols# +#quote(a:::``) +Error: attempt to use zero-length variable name + +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols# +#quote(a:::a) +a:::a + +##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols# +#quote(x <- 1) +x <- 1 + ##com.oracle.truffle.r.test.parser.TestParser.testHexLiterals# #+0xFFF [1] 4095 @@ -138969,6 +145562,18 @@ Error: unexpected input in "%0" #10^2^2 [1] 10000 +##com.oracle.truffle.r.test.parser.TestParser.testNewLinesInLiterals# +#"foo<<<NEWLINE>>>baraz" +[1] "foo\nbar\baz" + +##com.oracle.truffle.r.test.parser.TestParser.testNewLinesInLiterals# +#'foo<<<NEWLINE>>>baraz' +[1] "foo\nbar\baz" + +##com.oracle.truffle.r.test.parser.TestParser.testNewLinesInLiterals# +#`asdf<<<NEWLINE>>>asdf` <- 1; `asdf<<<NEWLINE>>>asdf` +[1] 1 + ##com.oracle.truffle.r.test.parser.TestParser.testNewLinesNesting#Output.IgnoreErrorMessage# #a <- 1:100; y <- 2; z <- 5; x <- (a[[{y <<<NEWLINE>>> * z}]]) Error: unexpected '*' in: @@ -139068,1200 +145673,6 @@ non-integer value 12345678909876543212L qualified with L; using numeric value #'\ ' == ' ' [1] TRUE -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.TestLENGTH#Output.MayIgnoreErrorContext# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- list(); x <- x <- append(x, rffi.LENGTH(1)); x <- append(x, rffi.LENGTH(c(1,2,3))); x <- append(x, rffi.LENGTH(list(1,2,3))); x <- append(x, rffi.LENGTH(expression(1,2))); ; detach("package:testrffi", unload=T); x } -[[1]] -[1] 1 - -[[2]] -[1] 3 - -[[3]] -[1] 3 - -[[4]] -[1] 2 - - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testAsFunctions#Output.MayIgnoreWarningContext# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- list(); x <- x <- append(x, rffi.asChar(1L)); x <- append(x, rffi.asInteger(1L)); x <- append(x, rffi.asReal(1L)); x <- append(x, rffi.asLogical(1L)); x <- append(x, rffi.asChar(2)); x <- append(x, rffi.asInteger(2)); x <- append(x, rffi.asReal(2)); x <- append(x, rffi.asLogical(2)); x <- append(x, rffi.asChar(2.2)); x <- append(x, rffi.asInteger(2.2)); x <- append(x, rffi.asReal(2.2)); x <- append(x, rffi.asLogical(2.2)); x <- append(x, rffi.asChar(T)); x <- append(x, rffi.asInteger(T)); x <- append(x, rffi.asReal(T)); x <- append(x, rffi.asLogical(T)); x <- append(x, rffi.asChar(integer())); x <- append(x, rffi.asInteger(integer())); x <- append(x, rffi.asReal(integer())); x <- append(x, rffi.asLogical(integer())); x <- append(x, rffi.asChar(numeric())); x <- append(x, rffi.asInteger(numeric())); x <- append(x, rffi.asReal(numeric())); x <- append(x, rffi.asLogical(numeric())); x <- append(x, rffi.asChar(logical())); x <- append(x, rffi.asInteger(logical())); x <- append(x, rffi.asReal(logical())); x <- append(x, rffi.asLogical(logical())); x <- append(x, rffi.asChar(character())); x <- append(x, rffi.asInteger(character())); x <- append(x, rffi.asReal(character())); x <- append(x, rffi.asLogical(character())); x <- append(x, rffi.asChar(c(5,6))); x <- append(x, rffi.asInteger(c(5,6))); x <- append(x, rffi.asReal(c(5,6))); x <- append(x, rffi.asLogical(c(5,6))); x <- append(x, rffi.asChar(c(2.3, 3.4))); x <- append(x, rffi.asInteger(c(2.3, 3.4))); x <- append(x, rffi.asReal(c(2.3, 3.4))); x <- append(x, rffi.asLogical(c(2.3, 3.4))); x <- append(x, rffi.asChar(c(T, F))); x <- append(x, rffi.asInteger(c(T, F))); x <- append(x, rffi.asReal(c(T, F))); x <- append(x, rffi.asLogical(c(T, F))); x <- append(x, rffi.asChar(as.symbol("sym"))); x <- append(x, rffi.asInteger(as.symbol("sym"))); x <- append(x, rffi.asReal(as.symbol("sym"))); x <- append(x, rffi.asLogical(as.symbol("sym"))); x <- append(x, rffi.asChar(list())); x <- append(x, rffi.asInteger(list())); x <- append(x, rffi.asReal(list())); x <- append(x, rffi.asLogical(list())); ; detach("package:testrffi", unload=T); x } -[[1]] -[1] "1" - -[[2]] -[1] 1 - -[[3]] -[1] 1 - -[[4]] -[1] TRUE - -[[5]] -[1] "2" - -[[6]] -[1] 2 - -[[7]] -[1] 2 - -[[8]] -[1] TRUE - -[[9]] -[1] "2.2" - -[[10]] -[1] 2 - -[[11]] -[1] 2.2 - -[[12]] -[1] TRUE - -[[13]] -[1] "TRUE" - -[[14]] -[1] 1 - -[[15]] -[1] 1 - -[[16]] -[1] TRUE - -[[17]] -[1] NA - -[[18]] -[1] NA - -[[19]] -[1] NA - -[[20]] -[1] NA - -[[21]] -[1] NA - -[[22]] -[1] NA - -[[23]] -[1] NA - -[[24]] -[1] NA - -[[25]] -[1] NA - -[[26]] -[1] NA - -[[27]] -[1] NA - -[[28]] -[1] NA - -[[29]] -[1] NA - -[[30]] -[1] NA - -[[31]] -[1] NA - -[[32]] -[1] NA - -[[33]] -[1] "5" - -[[34]] -[1] 5 - -[[35]] -[1] 5 - -[[36]] -[1] TRUE - -[[37]] -[1] "2.3" - -[[38]] -[1] 2 - -[[39]] -[1] 2.3 - -[[40]] -[1] TRUE - -[[41]] -[1] "TRUE" - -[[42]] -[1] 1 - -[[43]] -[1] 1 - -[[44]] -[1] TRUE - -[[45]] -[1] "sym" - -[[46]] -[1] NA - -[[47]] -[1] NA - -[[48]] -[1] NA - -[[49]] -[1] NA - -[[50]] -[1] NA - -[[51]] -[1] NA - -[[52]] -[1] NA - - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testListFunctions#Output.MayIgnoreErrorContext# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- list(); x <- x <- append(x, rffi.CAR(pairlist(1,2))); x <- append(x, rffi.CDR(pairlist(1,2))); x <- append(x, rffi.CAR(pairlist(x=1L, y=2L))); x <- append(x, rffi.CDR(pairlist(x=1L, y=2L))); ; detach("package:testrffi", unload=T); x } -[[1]] -[1] 1 - -[[2]] -[1] 2 - -[[3]] -[1] 1 - -$y -[1] 2 - - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI1# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.addInt(2L, 3L); detach("package:testrffi", unload=T); x } -[1] 5 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI10# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); a <- c(1L,2L,3L); x <- rffi.iterate_iptr(a); detach("package:testrffi", unload=T); x } -[1] 1 2 3 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI11# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.dotCModifiedArguments(c(0,1,2,3)); detach("package:testrffi", unload=T); x } -[[1]] -[1] 4 - -[[2]] -[1] 1 2 3 4 - -[[3]] -[1] 0.0 0.2 0.4 0.6 - -[[4]] -[1] TRUE FALSE FALSE FALSE - - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI12# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.dotExternalAccessArgs(1L, 3, c(1,2,3), c('a', 'b'), 'b', TRUE, as.raw(12)); detach("package:testrffi", unload=T); x } -[[1]] -[[1]][[1]] -NULL - -[[1]][[2]] -[1] 1 - - -[[2]] -[[2]][[1]] -NULL - -[[2]][[2]] -[1] 3 - - -[[3]] -[[3]][[1]] -NULL - -[[3]][[2]] -[1] 1 - - -[[4]] -[[4]][[1]] -NULL - -[[4]][[2]] -[1] "a" - - -[[5]] -[[5]][[1]] -NULL - -[[5]][[2]] -[1] "b" - - -[[6]] -[[6]][[1]] -NULL - -[[6]][[2]] -[1] 1 - - -[[7]] -[[7]][[1]] -NULL - -[[7]][[2]] -[1] 0c - - - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI13# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.dotExternalAccessArgs(x=1L, 3, c(1,2,3), y=c('a', 'b'), 'b', TRUE, as.raw(12)); detach("package:testrffi", unload=T); x } -[[1]] -[[1]][[1]] -x - -[[1]][[2]] -[1] 1 - - -[[2]] -[[2]][[1]] -NULL - -[[2]][[2]] -[1] 3 - - -[[3]] -[[3]][[1]] -NULL - -[[3]][[2]] -[1] 1 - - -[[4]] -[[4]][[1]] -y - -[[4]][[2]] -[1] "a" - - -[[5]] -[[5]][[1]] -NULL - -[[5]][[2]] -[1] "b" - - -[[6]] -[[6]][[1]] -NULL - -[[6]][[2]] -[1] 1 - - -[[7]] -[[7]][[1]] -NULL - -[[7]][[2]] -[1] 0c - - - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI14# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.invoke12(); detach("package:testrffi", unload=T); x } -[1] 12 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI15# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.TYPEOF(3L); detach("package:testrffi", unload=T); x } -[1] 13 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI16# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.isRString("hello"); detach("package:testrffi", unload=T); x } -[1] TRUE - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI17# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.isRString(NULL); detach("package:testrffi", unload=T); x } -[1] FALSE - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI18# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.interactive(); detach("package:testrffi", unload=T); x } -[1] FALSE - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI19# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- 1; x <- rffi.findvar("x", globalenv()); detach("package:testrffi", unload=T); x } -[1] 1 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI2# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.addDouble(2, 3); detach("package:testrffi", unload=T); x } -[1] 5 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI20# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- "12345"; x <- rffi.char_length(x); detach("package:testrffi", unload=T); x } -[1] 5 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI3# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.populateIntVector(5); detach("package:testrffi", unload=T); x } -[1] 0 1 2 3 4 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI4# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.populateLogicalVector(5); detach("package:testrffi", unload=T); x } -[1] TRUE NA FALSE FALSE FALSE - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI5# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.mkStringFromChar(); detach("package:testrffi", unload=T); x } -[1] "hello" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI6# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.mkStringFromBytes(); detach("package:testrffi", unload=T); x } -[1] "hello" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI7# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.null(); detach("package:testrffi", unload=T); x } -NULL - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI7C# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.null.C(); detach("package:testrffi", unload=T); x } -NULL - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI7E# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.null.E(); detach("package:testrffi", unload=T); x } -Error in .Call("null", PACKAGE = "foo") : - "null" not available for .Call() for package "foo" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI8# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.isRString(character(0)); detach("package:testrffi", unload=T); x } -[1] TRUE - -##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI9# -#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); a <- c(1L,2L,3L); x <- rffi.iterate_iarray(a); detach("package:testrffi", unload=T); x } -[1] 1 2 3 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(1L, 0); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(1L, 0) : - cannot coerce type 'integer' to vector of type 'NULL' - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(1L, 1); detach('package:testrffi', unload=T); x } -`1` - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(1L, 10); detach('package:testrffi', unload=T); x } -[1] TRUE - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(1L, 13); detach('package:testrffi', unload=T); x } -[1] 1 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(1L, 14); detach('package:testrffi', unload=T); x } -[1] 1 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(1L, 15); detach('package:testrffi', unload=T); x } -[1] 1+0i - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(1L, 16); detach('package:testrffi', unload=T); x } -[1] "1" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(1L, 19); detach('package:testrffi', unload=T); x } -[[1]] -[1] 1 - - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(1L, 24); detach('package:testrffi', unload=T); x } -[1] 01 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 0); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(2, 0) : - cannot coerce type 'double' to vector of type 'NULL' - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 1); detach('package:testrffi', unload=T); x } -`2` - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 10); detach('package:testrffi', unload=T); x } -[1] TRUE - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 13); detach('package:testrffi', unload=T); x } -[1] 2 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 14); detach('package:testrffi', unload=T); x } -[1] 2 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 15); detach('package:testrffi', unload=T); x } -[1] 2+0i - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 16); detach('package:testrffi', unload=T); x } -[1] "2" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 19); detach('package:testrffi', unload=T); x } -[[1]] -[1] 2 - - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 24); detach('package:testrffi', unload=T); x } -[1] 02 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 0); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(2.2, 0) : - cannot coerce type 'double' to vector of type 'NULL' - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 1); detach('package:testrffi', unload=T); x } -`2.2` - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 10); detach('package:testrffi', unload=T); x } -[1] TRUE - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 13); detach('package:testrffi', unload=T); x } -[1] 2 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 14); detach('package:testrffi', unload=T); x } -[1] 2.2 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 15); detach('package:testrffi', unload=T); x } -[1] 2.2+0i - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 16); detach('package:testrffi', unload=T); x } -[1] "2.2" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 19); detach('package:testrffi', unload=T); x } -[[1]] -[1] 2.2 - - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 24); detach('package:testrffi', unload=T); x } -[1] 02 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 0); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(T, 0) : - cannot coerce type 'logical' to vector of type 'NULL' - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 1); detach('package:testrffi', unload=T); x } -`TRUE` - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 10); detach('package:testrffi', unload=T); x } -[1] TRUE - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 13); detach('package:testrffi', unload=T); x } -[1] 1 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 14); detach('package:testrffi', unload=T); x } -[1] 1 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 15); detach('package:testrffi', unload=T); x } -[1] 1+0i - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 16); detach('package:testrffi', unload=T); x } -[1] "TRUE" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 19); detach('package:testrffi', unload=T); x } -[[1]] -[1] TRUE - - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 24); detach('package:testrffi', unload=T); x } -[1] 01 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 0); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(c(2.3, 3.4), 0) : - cannot coerce type 'double' to vector of type 'NULL' - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 1); detach('package:testrffi', unload=T); x } -`2.3` - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 10); detach('package:testrffi', unload=T); x } -[1] TRUE TRUE - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 13); detach('package:testrffi', unload=T); x } -[1] 2 3 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 14); detach('package:testrffi', unload=T); x } -[1] 2.3 3.4 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 15); detach('package:testrffi', unload=T); x } -[1] 2.3+0i 3.4+0i - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 16); detach('package:testrffi', unload=T); x } -[1] "2.3" "3.4" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 19); detach('package:testrffi', unload=T); x } -[[1]] -[1] 2.3 - -[[2]] -[1] 3.4 - - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 24); detach('package:testrffi', unload=T); x } -[1] 02 03 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 0); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(c(5, 6), 0) : - cannot coerce type 'double' to vector of type 'NULL' - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 1); detach('package:testrffi', unload=T); x } -`5` - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 10); detach('package:testrffi', unload=T); x } -[1] TRUE TRUE - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 13); detach('package:testrffi', unload=T); x } -[1] 5 6 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 14); detach('package:testrffi', unload=T); x } -[1] 5 6 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 15); detach('package:testrffi', unload=T); x } -[1] 5+0i 6+0i - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 16); detach('package:testrffi', unload=T); x } -[1] "5" "6" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 19); detach('package:testrffi', unload=T); x } -[[1]] -[1] 5 - -[[2]] -[1] 6 - - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 24); detach('package:testrffi', unload=T); x } -[1] 05 06 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 0); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(c(T, F), 0) : - cannot coerce type 'logical' to vector of type 'NULL' - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 1); detach('package:testrffi', unload=T); x } -`TRUE` - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 10); detach('package:testrffi', unload=T); x } -[1] TRUE FALSE - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 13); detach('package:testrffi', unload=T); x } -[1] 1 0 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 14); detach('package:testrffi', unload=T); x } -[1] 1 0 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 15); detach('package:testrffi', unload=T); x } -[1] 1+0i 0+0i - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 16); detach('package:testrffi', unload=T); x } -[1] "TRUE" "FALSE" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 19); detach('package:testrffi', unload=T); x } -[[1]] -[1] TRUE - -[[2]] -[1] FALSE - - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 24); detach('package:testrffi', unload=T); x } -[1] 01 00 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 0); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(character(), 0) : - cannot coerce type 'character' to vector of type 'NULL' - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 1); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(character(), 1) : - invalid data of mode 'character' (too short) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 10); detach('package:testrffi', unload=T); x } -logical(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 13); detach('package:testrffi', unload=T); x } -integer(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 14); detach('package:testrffi', unload=T); x } -numeric(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 15); detach('package:testrffi', unload=T); x } -complex(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 16); detach('package:testrffi', unload=T); x } -character(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 19); detach('package:testrffi', unload=T); x } -list() - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 24); detach('package:testrffi', unload=T); x } -raw(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 0); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(integer(), 0) : - cannot coerce type 'integer' to vector of type 'NULL' - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 1); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(integer(), 1) : - invalid data of mode 'integer' (too short) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 10); detach('package:testrffi', unload=T); x } -logical(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 13); detach('package:testrffi', unload=T); x } -integer(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 14); detach('package:testrffi', unload=T); x } -numeric(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 15); detach('package:testrffi', unload=T); x } -complex(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 16); detach('package:testrffi', unload=T); x } -character(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 19); detach('package:testrffi', unload=T); x } -list() - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 24); detach('package:testrffi', unload=T); x } -raw(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 0); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(list(), 0) : - unimplemented type 'list' in 'coerceVectorList' - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 1); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(list(), 1) : - invalid type/length (symbol/0) in vector allocation - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 10); detach('package:testrffi', unload=T); x } -logical(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 13); detach('package:testrffi', unload=T); x } -integer(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 14); detach('package:testrffi', unload=T); x } -numeric(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 15); detach('package:testrffi', unload=T); x } -complex(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 16); detach('package:testrffi', unload=T); x } -character(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 19); detach('package:testrffi', unload=T); x } -list() - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 24); detach('package:testrffi', unload=T); x } -raw(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 0); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(logical(), 0) : - cannot coerce type 'logical' to vector of type 'NULL' - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 1); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(logical(), 1) : - invalid data of mode 'logical' (too short) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 10); detach('package:testrffi', unload=T); x } -logical(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 13); detach('package:testrffi', unload=T); x } -integer(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 14); detach('package:testrffi', unload=T); x } -numeric(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 15); detach('package:testrffi', unload=T); x } -complex(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 16); detach('package:testrffi', unload=T); x } -character(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 19); detach('package:testrffi', unload=T); x } -list() - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 24); detach('package:testrffi', unload=T); x } -raw(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 0); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(numeric(), 0) : - cannot coerce type 'double' to vector of type 'NULL' - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 1); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(numeric(), 1) : - invalid data of mode 'double' (too short) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 10); detach('package:testrffi', unload=T); x } -logical(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 13); detach('package:testrffi', unload=T); x } -integer(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 14); detach('package:testrffi', unload=T); x } -numeric(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 15); detach('package:testrffi', unload=T); x } -complex(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 16); detach('package:testrffi', unload=T); x } -character(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 19); detach('package:testrffi', unload=T); x } -list() - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 24); detach('package:testrffi', unload=T); x } -raw(0) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(1L,names='a',dim=c(1,1),myattr='q'), 0); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(structure(1L, names = "a", dim = c(1, 1), myattr = "q"), : - cannot coerce type 'integer' to vector of type 'NULL' - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(1L,names='a',dim=c(1,1),myattr='q'), 1); detach('package:testrffi', unload=T); x } -`1` - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(1L,names='a',dim=c(1,1),myattr='q'), 10); detach('package:testrffi', unload=T); x } - [,1] -[1,] TRUE -attr(,"names") -[1] "a" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(1L,names='a',dim=c(1,1),myattr='q'), 13); detach('package:testrffi', unload=T); x } - [,1] -[1,] 1 -attr(,"names") -[1] "a" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(1L,names='a',dim=c(1,1),myattr='q'), 14); detach('package:testrffi', unload=T); x } - [,1] -[1,] 1 -attr(,"names") -[1] "a" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(1L,names='a',dim=c(1,1),myattr='q'), 15); detach('package:testrffi', unload=T); x } - [,1] -[1,] 1+0i -attr(,"names") -[1] "a" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(1L,names='a',dim=c(1,1),myattr='q'), 16); detach('package:testrffi', unload=T); x } - [,1] -[1,] "1" -attr(,"names") -[1] "a" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(1L,names='a',dim=c(1,1),myattr='q'), 19); detach('package:testrffi', unload=T); x } -$a -[1] 1 - - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(1L,names='a',dim=c(1,1),myattr='q'), 24); detach('package:testrffi', unload=T); x } - [,1] -[1,] 01 -attr(,"names") -[1] "a" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 0); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(structure(2.2, names = "b", dim = c(1, 1), : - cannot coerce type 'double' to vector of type 'NULL' - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 1); detach('package:testrffi', unload=T); x } -`2.2` - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 10); detach('package:testrffi', unload=T); x } - [,1] -[1,] TRUE -attr(,"names") -[1] "b" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 13); detach('package:testrffi', unload=T); x } - [,1] -[1,] 2 -attr(,"names") -[1] "b" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 14); detach('package:testrffi', unload=T); x } - [,1] -[1,] 2.2 -attr(,"names") -[1] "b" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 15); detach('package:testrffi', unload=T); x } - [,1] -[1,] 2.2+0i -attr(,"names") -[1] "b" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 16); detach('package:testrffi', unload=T); x } - [,1] -[1,] "2.2" -attr(,"names") -[1] "b" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 19); detach('package:testrffi', unload=T); x } -$b -[1] 2.2 - - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 24); detach('package:testrffi', unload=T); x } - [,1] -[1,] 02 -attr(,"names") -[1] "b" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 0); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(structure(T, names = "c", dim = c(1, 1), myattr = "q"), : - cannot coerce type 'logical' to vector of type 'NULL' - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 1); detach('package:testrffi', unload=T); x } -`TRUE` - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 10); detach('package:testrffi', unload=T); x } - [,1] -[1,] TRUE -attr(,"names") -[1] "c" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 13); detach('package:testrffi', unload=T); x } - [,1] -[1,] 1 -attr(,"names") -[1] "c" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 14); detach('package:testrffi', unload=T); x } - [,1] -[1,] 1 -attr(,"names") -[1] "c" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 15); detach('package:testrffi', unload=T); x } - [,1] -[1,] 1+0i -attr(,"names") -[1] "c" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 16); detach('package:testrffi', unload=T); x } - [,1] -[1,] "TRUE" -attr(,"names") -[1] "c" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 19); detach('package:testrffi', unload=T); x } -$c -[1] TRUE - - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 24); detach('package:testrffi', unload=T); x } - [,1] -[1,] 01 -attr(,"names") -[1] "c" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'), 0); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(structure(list(1, "42"), names = c("q", "w"), : - unimplemented type 'list' in 'coerceVectorList' - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'), 1); detach('package:testrffi', unload=T); x } -Error in rffi.coerceVector(structure(list(1, "42"), names = c("q", "w"), : - invalid type/length (symbol/2) in vector allocation - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'), 10); detach('package:testrffi', unload=T); x } - q w -TRUE NA - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'), 13); detach('package:testrffi', unload=T); x } - q w - 1 42 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'), 14); detach('package:testrffi', unload=T); x } - q w - 1 42 - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'), 15); detach('package:testrffi', unload=T); x } - q w - 1+0i 42+0i - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'), 16); detach('package:testrffi', unload=T); x } - q w - "1" "42" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'), 19); detach('package:testrffi', unload=T); x } - [,1] -[1,] 1 -[2,] "42" -attr(,"names") -[1] "q" "w" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'), 24); detach('package:testrffi', unload=T); x } - q w -01 2a - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 20); detach('package:testrffi', unload=T); x } -expression(2) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 20); detach('package:testrffi', unload=T); x } -expression(2.2) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 20); detach('package:testrffi', unload=T); x } -expression(TRUE) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 20); detach('package:testrffi', unload=T); x } -expression(2.3, 3.4) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 20); detach('package:testrffi', unload=T); x } -expression(5, 6) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 20); detach('package:testrffi', unload=T); x } -expression(TRUE, FALSE) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 20); detach('package:testrffi', unload=T); x } -expression() - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 20); detach('package:testrffi', unload=T); x } -expression() - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 20); detach('package:testrffi', unload=T); x } -expression() - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 20); detach('package:testrffi', unload=T); x } -expression() - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 20); detach('package:testrffi', unload=T); x } -expression() - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 20); detach('package:testrffi', unload=T); x } -expression(2.2) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 20); detach('package:testrffi', unload=T); x } -expression(TRUE) - -##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Ignored.Unimplemented# -#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'x'), names=c('q','w'),dim=c(2,1),myattr='q'), 20); detach('package:testrffi', unload=T); x } -expression(q = 1, w = "x") -attr(,"names") -[1] "q" "w" -attr(,"myattr") -[1] "q" - -##com.oracle.truffle.r.test.rffi.TestUserRNG.testUserRNG# -#{ dyn.load("com.oracle.truffle.r.test.native/urand/lib/liburand.so"); RNGkind("user"); print(RNGkind()); set.seed(4567); runif(10) } -[1] "user-supplied" "Inversion" - [1] 0.45336386 0.38848030 0.94576608 0.11726267 0.21542351 0.08672997 - [7] 0.35201276 0.16919220 0.93579263 0.26084486 - ##com.oracle.truffle.r.test.rng.TestRRNG.testDirectReadingSeed# #invisible(runif(1)); length(.Random.seed) [1] 626 @@ -140398,92 +145809,3 @@ In runif(3) : #invisible(runif(5)); RNGkind('Marsaglia-Multicarry'); set.seed(2); runif(5); [1] 0.8431527 0.5749091 0.1531976 0.3460321 0.2313936 -##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout# -#{ library(KernSmooth, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:KernSmooth"); } -KernSmooth 2.23 loaded -Copyright M. P. Wand 1997-2009 - -##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout# -#{ library(MASS, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:MASS"); } - -##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout# -#{ library(Matrix, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:Matrix"); } - -##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout# -#{ library(boot, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:boot"); } - -##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout# -#{ library(class, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:class"); } - -##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout# -#{ library(cluster, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:cluster"); } - -##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout# -#{ library(codetools, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:codetools"); } - -##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout# -#{ library(foreign, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:foreign"); } - -##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout# -#{ library(lattice, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:lattice"); } - -##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout# -#{ library(nlme, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:nlme"); } - -##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout# -#{ library(nnet, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:nnet"); } - -##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout# -#{ library(rpart, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:rpart"); } - -##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout# -#{ library(spatial, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:spatial"); } - -##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout# -#{ library(survival, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:survival"); } - -##com.oracle.truffle.r.test.rpackages.TestS4TestPackage.testS4Execute# -#{ library("tests4", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r<-print(tests4:::inspect.vehicle(new("Car"), new("Inspector"))); detach("package:tests4"); unloadNamespace("tests4"); r } -Looking for rust -Checking seat belts -NULL -NULL - -##com.oracle.truffle.r.test.rpackages.TestS4TestPackage.testS4Execute# -#{ library("tests4", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r<-print(tests4:::inspect.vehicle(new("Car"), new("StateInspector"))); detach("package:tests4"); unloadNamespace("tests4"); r } -Looking for rust -Checking seat belts -Checking insurance -NULL -NULL - -##com.oracle.truffle.r.test.rpackages.TestS4TestPackage.testS4Execute# -#{ library("tests4", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r<-print(tests4:::inspect.vehicle(new("Truck"), new("Inspector"))); detach("package:tests4"); unloadNamespace("tests4"); r } -Looking for rust -Checking cargo attachments -NULL -NULL - -##com.oracle.truffle.r.test.rpackages.TestS4TestPackage.testS4Execute# -#{ library("tests4", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r<-print(tests4:::inspect.vehicle(new("Truck"), new("StateInspector"))); detach("package:tests4"); unloadNamespace("tests4"); r } -Looking for rust -Checking cargo attachments -NULL -NULL - -##com.oracle.truffle.r.test.rpackages.TestS4TestPackage.testS4Load# -#{ library("tests4", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:tests4"); unloadNamespace("tests4") } - -##com.oracle.truffle.r.test.rpackages.TestVanillaPackage.testLoadVanilla# -#{ library("vanilla", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r <- vanilla(); detach("package:vanilla"); r } -[1] "A vanilla R package" -[1] "A vanilla R package" - -##com.oracle.truffle.r.test.rpackages.TestVanillaPackage.testQualifiedReplacement# -#{ library("vanilla", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r<-42; vanilla::foo(r)<-7; detach("package:vanilla"); r } -[1] 7 - -##com.oracle.truffle.r.test.rpackages.TestVanillaPackage.testSimpleFunction# -#{ library("vanilla", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r <- functionTest(c(1,2,3,4,5,6),8:10); detach("package:vanilla"); r } -[1] 2 3 4 5 6 7 8 9 10 - diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/FastRJUnitWrapper.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/FastRJUnitWrapper.java index eb1259935f1a066b448c81a3ff805a57f3d81c42..b38580ea0b6b5da7eb45fa6d70df00fd11bd37f7 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/FastRJUnitWrapper.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/FastRJUnitWrapper.java @@ -106,9 +106,8 @@ public class FastRJUnitWrapper { ArrayList<Class<?>> tests = new ArrayList<>(1000); try (BufferedReader br = new BufferedReader(new FileReader(testsFile))) { - String className; - while ((className = br.readLine()) != null) { - tests.add(Class.forName(className)); + while ((testClassName = br.readLine()) != null) { + tests.add(Class.forName(testClassName)); } } catch (IOException ioe) { ioe.printStackTrace(); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/NextMethod.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/NextMethod.R new file mode 100644 index 0000000000000000000000000000000000000000..5a9f104559e2557d3167f0b2bded94493762c8e3 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/NextMethod.R @@ -0,0 +1,24 @@ +setClass("A") +setClass("B", contains = "A") +setClass("C", contains = "A") + +setClass("D", representation(name = "character")) + +setGeneric("foo.bar", function(x, y) { + standardGeneric("foo.bar") + }) + + setMethod("foo.bar", + signature(x = "C", y = "D"), + function(x, y) { + callNextMethod() + message("foo.bar(C, D)") + }) + + setMethod("foo.bar", + signature(x = "A", y = "D"), + function(x, y) { + message("foo.bar(A, D)") + }) + +foo.bar(new("C"), new("D")) diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/NextMethod1.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/NextMethod1.R new file mode 100644 index 0000000000000000000000000000000000000000..86e89df7335dcfad165788782c40b97a5cab17e0 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/NextMethod1.R @@ -0,0 +1,44 @@ +setClass("A") +setClass("B", contains = "A") +setClass("C", contains = "A") + +setClass("D", representation(id = "numeric")) +setClass("E", contains = "D") + + +setGeneric("foo.bar", function(x, y) { + standardGeneric("foo.bar") + }) + + setMethod("foo.bar", + signature(x = "C", y = "D"), + function(x, y) { + callNextMethod() + message("foo.bar(C, D)") + }) + + setMethod("foo.bar", + signature(x = "A", y = "D"), + function(x, y) { + message("foo.bar(A, D)") + }) + + setMethod("foo.bar", + signature(x = "B", y = "D"), + function(x, y) { + callNextMethod() + message("foo.bar(B, D)") + }) + +foo.bar(new("B"), new("D")) + +setMethod("foo.bar", + signature(x = "C", y = "E"), + function(x, y) { + callNextMethod() + message("foo.bar(C, E)") +}) + +foo.bar(new("C"), new("E")) + +foo.bar(new("B"), new("E")) diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding0.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding0.R new file mode 100644 index 0000000000000000000000000000000000000000..1eb24d837692440d336fdc8589f475239a67586c --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding0.R @@ -0,0 +1,16 @@ +f <- local( { + x <- 1 + function(v) { + if (missing(v)) + cat("get\n") + else { + cat("set\n") + x <<- v + } + x + } +}) +makeActiveBinding("fred", f, .GlobalEnv) +print(fred) +fred <- 2 +print(fred) \ No newline at end of file diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding1.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding1.R new file mode 100644 index 0000000000000000000000000000000000000000..dd71ebe2c4c38c88cf20d6010eaca972fb28f7d1 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding1.R @@ -0,0 +1,14 @@ +f <- local( { + x <- 1 + function(v) { + if (missing(v)) + cat("get\n") + else { + cat("set\n") + x <<- v + } + x + } +}) +makeActiveBinding("fred", f, .GlobalEnv) +cat(fred) \ No newline at end of file diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding2.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding2.R new file mode 100644 index 0000000000000000000000000000000000000000..11070d3a0f401b838ac77f5180997a64c787af79 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding2.R @@ -0,0 +1,16 @@ +f <- local( { + x <- 1 + function(v) { + if (missing(v)) + cat("get\n") + else { + cat("set\n") + x <<- v + } + x + } +}) +makeActiveBinding("fred", f, .GlobalEnv) +foo <- function() { + fred + 1 +} \ No newline at end of file diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding3.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding3.R new file mode 100644 index 0000000000000000000000000000000000000000..b54876d335bda0e33c94a364aaf84c4cafece278 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding3.R @@ -0,0 +1,18 @@ +f <- local( { + x <- 1 + function(v) { + if (missing(v)) + cat("get\n") + else { + cat("set\n") + x <<- v + } + x + } +}) +makeActiveBinding("fred", f, .GlobalEnv) +foo <- function(x) { + fred <<- x +} +foo(3) +print(fred) \ No newline at end of file diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/dispatch.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/dispatch.R new file mode 100644 index 0000000000000000000000000000000000000000..d9a3c518faceb4552670a7e1612cd716b835a597 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/dispatch.R @@ -0,0 +1,10 @@ +foo.bar <- function(x, y, z) { print(x); print(y); print(z) } + +setClass("A", representation(a = "numeric")) +setClass("B", representation(b = "logical")) +setMethod("foo.bar", signature = list(y = "A", z = "B"), function(x, y, z) { print("primitive, A, B") }) +setMethod("foo.bar", signature = list(y = "B", z = "A"), function(x, y, z) { print("primitive, B, A") }) + +foo.bar(1, 2, 3) +foo.bar(1, new("A"), new("B")) +foo.bar(1, new("B"), new("A")) diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses0.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses0.R new file mode 100644 index 0000000000000000000000000000000000000000..62a83df43ef1198761a47cd390a76c77e616f639 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses0.R @@ -0,0 +1,84 @@ +#IgnoreErrorContext +# Create a new reference class, and an instance of it +gen <- setRefClass("myRefClass", fields=list(aa="integer", bb="ANY")) +x <- gen$new(aa=123L, bb=3.4) +# Extract and set a field +x$aa +x$aa <- 456L +## Not run: +# Generate an error on trying to set the field to a non-integer +try(x$aa <- "notAnInteger") +## End(Not run) +# Can put any value in a field of type "ANY" +x$bb <- "foo" +# One way to create a new object: +# Call the "new" method on a refObjectGenerator object +xClass <- getRefClass("myRefClass") +x <- xClass$new(aa=123L, bb=3.4) + +# A second way to create a new object: +# Use the refObjectGenerator as a function +xClass <- getRefClass("myRefClass") +x <- xClass(aa=123L, bb=3.4) + +# A third way to create a new object: +# Call the "new" function with the class name +x <- new("myRefClass", aa=123L, bb=3.4) + +# Make reference class inheriting from the above class +gen2 <- setRefClass("myRefClass2", contains="myRefClass", + fields=list(cc="character")) +# Create instance specifying fields (including inherited ones) +x2 <- gen2$new(aa=1L, bb=2.3, cc="foo") + +# Define reference class with a method +gen3 <- setRefClass("myRefClass3", fields=list(dd="numeric"), + methods=list(getval=function() dd, + setval=function(value) dd <<- value)) +x3 <- gen3$new(dd=1.2) +# Call methods to extract/set value of "dd" field +x3$getval() # returns 1.2 +x3$setval(3.4) +x3$getval() # now returns 3.4 +## Not run: +# Gives error if you try to set field to incorrect class +try(x3$setval("foo")) +## End(Not run) + +# Define subclass of the above class with a method calling callSuper +gen4 <- setRefClass("myRefClass4", contains="myRefClass3", + methods=list(getval=function() 2*callSuper())) +x4 <- gen4$new(dd=100) +x4$getval() # returns 200 + +# Define method with an "initialize" method modifying field values +# field "x" is set to twice the specified value, defaulting to 100 +# field "y" is set to "none" if not specified explicitly +gen5 <- setRefClass("myRefClass5", fields=list(x="numeric",y="character"), + methods=list(initialize=function(..., x=100L) + {x <<- 2*x; y <<- "none"; callSuper(...)})) +gen5$new() # initializes field "x" to 200, "y" to "none" +gen5$new(x=10) # initializes field "x" to 20, "y" to "none" +gen5$new(y="abc") # initializes field "x" to 200, "y" to "abc" + +# Define a field as a function used for an active binding +gen6 <- setRefClass("myRefClass6", + methods=list(initialize=function(...) + {saveVal <<- 0; numSet <<- 0; callSuper(...)}), + fields=list(saveVal="numeric", numSet="numeric", value=function(value) { + if(missing(value)) { + saveVal + } else { + numSet <<- numSet+1 + saveVal <<- value + value + }})) +x6 <- gen6$new() +x6$value # returns 0 +x6$numSet # returns 0 +x6$value <- 123 +x6$value # returns 123 +x6$numSet # returns 1 +x6$value <- 456 +x6$value # returns 456 +x6$numSet # returns 2 \ No newline at end of file diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses1.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses1.R new file mode 100644 index 0000000000000000000000000000000000000000..73ac4e62b816a4b06d92bf52019e994cba9b60e5 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses1.R @@ -0,0 +1,5 @@ +setRefClass('A5R5', methods = list(foo = function() { print('A5R5$foo') })) +setRefClass('B5R5', methods = list(foo = function() { print('B5R5$foo') })) +C5R5 <- setRefClass('C5R5', contains = c('A5R5', 'B5R5')) +obj <- C5R5$new() +obj$foo() \ No newline at end of file diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses2.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses2.R new file mode 100644 index 0000000000000000000000000000000000000000..3d8561e95081aa6822896e21b0d0180f33748e7f --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses2.R @@ -0,0 +1,25 @@ +MatrixClass = setRefClass( +Class = "MatrixClass", +fields = list( +dataMat = "matrix", +detMat ="numeric", +inverseMat = "matrix")) + +MatrixClass$methods( +initialize = function(extMat = diag(1), ...){ + +dataMat <<- extMat + +detMat <<- det(dataMat) +if(abs(detMat) > 1e-7 ){ +inverseMat <<- solve(dataMat) +}else{ +inverseMat <<- NULL +} + +callSuper(...) +}) + +extMat = diag(3) * c(1,2,3) +newMat = MatrixClass$new(extMat) +newMat \ No newline at end of file diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java new file mode 100644 index 0000000000000000000000000000000000000000..9d31793e24abbdffa899fb287f84ec254eac9c4a --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java @@ -0,0 +1,128 @@ +/* + * 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.S4; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; +import com.oracle.truffle.r.test.TestTrait; + +// Checkstyle: stop LineLength + +public class TestR5 extends TestBase { + + /** + * {@code suppressMessages} is needed to suppress messages about codetools not being available. + */ + private void assertSuppress(String test) { + assertEval("print(suppressMessages({" + test + "}))"); + } + + private void assertSuppress(TestTrait trait, String test) { + assertEval(trait, "print(suppressMessages({" + test + "}))"); + } + + @Test + public void testAllocation() { + assertEval("{ DummyClass0 <- setRefClass('DummyClass0'); DummyClass0$new() }"); + assertEval("{ DummyClass1 <- setRefClass('DummyClass1'); is(DummyClass1, 'refClass') }"); + assertEval("{ DummyClass2 <- setRefClass('DummyClass2'); obj <- DummyClass2$new(); is(obj, 'refObject') }"); + assertEval("{ fooClass <- setRefClass('Foo6R5', fields = list( a = 'numeric')); fooClass$new(a = 1) }"); + assertEval("{ fooClass <- setRefClass('Foo7R5', fields = list( a = 'numeric')); fooClass$new(1) }"); + assertEval("{ setRefClass('Foo16R5'); ls(topenv(parent.frame()), all.names = T) }"); + assertEval("env0 <- new.env(); setRefClass('Foo17R5', where = env0); ls(topenv(parent.frame()), all.names = T); ls(env0, all.names = T)"); + } + + @Test + public void testAttributes() { + assertEval("{ clazz <- setRefClass('Foo13R5'); clazz$methods() }"); + } + + @Test + public void testReferenceSemantics() { + assertEval("fooClass <- setRefClass('Foo12R5', fields = list( a = 'numeric')); obj0 <- fooClass$new(a = 1); obj1 <- obj0; obj0$a; obj1$a; obj0$a <- 999; obj0$a; obj1$a"); + } + + @Test + public void testInstanceMethods() { + assertSuppress("{ clazz <- setRefClass('Foo0R5', c('a', 'b')); clazz$methods(mean = function() { (a + b) / 2 }); obj <- clazz$new(a = 1, b = 5); obj$mean() }"); + assertEval("{ clazz <- setRefClass('Foo1R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); cobj <- obj$copy(); obj$a; cobj$a; obj$a <- 10; obj$a; cobj$a}"); + assertEval("clazz <- setRefClass('Foo2R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); obj$field('a'); obj$field('b')"); + assertEval("clazz <- setRefClass('Foo3R5', c('a', 'b')); obj <- clazz$new(); obj$initFields(a = 5, b = 6)"); + assertEval(Output.IgnoreErrorContext, "{ clazz <- setRefClass('Foo4R5', c('a', 'b')); clazz$accessors() }"); + assertEval("{ clazz <- setRefClass('Foo5R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); attributes(obj$getRefClass())$className }"); + assertSuppress("{ clazz <- setRefClass('Foo12R5', fields = list(a = 'numeric'), methods = list(inc = function() { a <<- a+1 })); obj <- clazz$new(a = 0); obj$inc(); obj$a }"); + assertEval("{ clazz <- setRefClass('Foo13R5'); obj <- clazz$new(); obj$inexistingMethod() }"); + assertSuppress("{ clazz <- setRefClass('Foo28R5', fields = list(a = 'numeric'), methods = list(inc = function() { a <<- a+1 })); obj <- clazz$new(a = 0); obj$inc(); obj$a }"); + + // constructor + assertSuppress("{ clazz <- setRefClass('Foo15R5', fields = c('a'), methods = list(initialize = function() { a <<- 123 })); obj <- clazz$new(); obj$a }"); + assertSuppress("{ setRefClass('A6R5', fields = c('a'), methods = list(initialize = function() { a <<- 'hello' })); clazz <- setRefClass('B6R5', fields = c('a'), contains = 'A6R5'); obj <- clazz$new(); obj$a }"); + + assertEval(Ignored.Unknown, + "{ clazz <- setRefClass('Foo18R5', fields = c('a'), methods = list(initialize = function() a <<- 456, finalize = function() { print(sprintf('finalizer: %d', a)) } )); (function () { x <- clazz$new(); print('fun') })(); gc() }"); + } + + @Test + public void testCheckedAssign() { + assertEval("clazz <- setRefClass('Foo8R5', fields = list(a = 'numeric')); obj <- clazz$new(); bindingIsActive('a', as.environment(obj))"); + assertEval("clazz <- setRefClass('Foo9R5', fields = list(a = 'numeric')); obj <- clazz$new(); bindingIsActive('a', as.environment(obj)); obj$a <- 123; bindingIsActive('a', as.environment(obj))"); + assertEval("clazz <- setRefClass('Foo10R5', fields = list(a = 'numeric')); obj <- clazz$new(); obj$a <- 10; obj$a; obj$a <- 'hello'; obj$a"); + assertEval("clazz <- setRefClass('Foo11R5', fields = list(a = 'character')); obj <- clazz$new(); obj$a <- 'hello'; obj$a; obj$a <- 10; obj$a"); + } + + @Test + public void testFieldAccess() { + assertEval("{ clazz <- setRefClass('Foo14R5'); obj <- clazz$new(); obj$inexistingMethod() }"); + assertEval("{ clazz <- setRefClass('Foo14R5', fields = c('a')); obj <- clazz$new(); obj$a }"); + assertEval("{ clazz <- setRefClass('Foo14R5', fields = c('a')); obj <- clazz$new(a = 1); print(obj$a); obj$a <- 'hello'; print(obj$a) }"); + + // list/modify methods + assertEval("{ clazz <- setRefClass('Foo19R5'); clazz$methods('inexistingMethod') }"); + assertSuppress(Ignored.OutputFormatting, "clazz <- setRefClass('Foo20R5', methods = list(foo = function() NULL)); clazz$methods('foo')"); + assertSuppress("clazz <- setRefClass('Foo21R5', methods = list(foo = function() NULL)); clazz$new()$foo(); clazz$methods(foo = function(x) x); clazz$new()$foo(3)"); + + // list available fields + assertEval("{ clazz <- setRefClass('Foo22R5'); clazz$fields() }"); + assertEval("{ clazz <- setRefClass('Foo23R5', fields = c('a', 'b', 'c')); clazz$fields() }"); + assertEval("{ clazz <- setRefClass('Foo24R5', fields = list(a = 'numeric')); clazz$fields() }"); + assertEval("{ clazz <- setRefClass('Foo25R5', fields = list(a = 'numeric', b = 'character', c = 'raw')); clazz$fields() }"); + + // make field read-only; one assignment is allowed + assertEval("{ clazz <- setRefClass('Foo26R5', fields = list(a = 'numeric')); clazz$lock('a'); obj <- clazz$new(); obj$a <- 10; obj$a }"); + assertEval("{ clazz <- setRefClass('Foo27R5', fields = list(a = 'numeric')); clazz$lock('a'); obj <- clazz$new(); obj$a <- 10; obj$a <- 20 }"); + + // generate getter and setter + assertEval(Output.ImprovedErrorContext, "{ clazz <- setRefClass('Foo28R5', fields = list(a = 'numeric', b = 'character')); clazz$accessors(); clazz$methods() }"); + } + + @Test + public void testInheritance() { + assertEval("A0R5 <- setRefClass('A0R5', field = list(a = 'numeric')); B0R5 <- setRefClass('B0R5', contains = 'A0R5'); obj <- B0R5$new(a = 1); obj$a"); + assertSuppress("A1R5 <- setRefClass('A1R5', methods = list(foo = function() { print('hello') })); B1R5 <- setRefClass('B1R5', contains = 'A1R5'); obj <- B1R5$new(); obj$foo()"); + assertSuppress("A2R5 <- setRefClass('A2R5', methods = list(foo = function() { print('hello') })); B2R5 <- setRefClass('B2R5', methods = list(foo = function() { print('world') }), contains = 'A2R5'); obj <- B2R5$new(); obj$foo()"); + assertSuppress("A3R5 <- setRefClass('A3R5', methods = list(foo = function() { print('hello') })); B3R5 <- setRefClass('B3R5', methods = list(foo = function() { callSuper(); print('world') }), contains = 'A3R5'); obj <- B3R5$new(); obj$foo()"); + assertSuppress(Ignored.OutputFormatting, "{ setRefClass('A4R5', fields = c('a')); setRefClass('B4R5', contains = 'A4R5', methods = list(set_a = function(a){ a <<- a })) }"); + assertEval("A5R5 <- setRefClass('A5R5', field = c('a'), methods = list(initialize <- function() { a <<- 0 })); B5R5 <- setRefClass('B5R5', field = c('a'), methods = list(initialize <- function() { a <<- 'hello' })); C5R5 <- setRefClass('C5R5', contains = c('A5R5', 'B5R5')); obj <- C5R5$new(); obj$a <- raw(0)"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java index 30a6d6d91d5452eaf144a3e67ac8336438ae1ee9..a69b6a84e1360650ad23ec0f8c6f9a05431139e5 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.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 @@ -32,6 +32,12 @@ import com.oracle.truffle.r.test.TestRBase; * Tests for the S4 object model implementation. */ public class TestS4 extends TestRBase { + + @Override + protected String getTestDir() { + return "S4"; + } + @Test public void testSlotAccess() { assertEval("{ `@`(getClass(\"ClassUnionRepresentation\"), virtual) }"); @@ -56,6 +62,10 @@ public class TestS4 extends TestRBase { assertEval(Output.IgnoreErrorContext, "{ x<-NULL; `@`(x, foo) }"); assertEval(Output.IgnoreErrorContext, "{ x<-NULL; x@foo }"); assertEval("{ x<-paste0(\".\", \"Data\"); y<-42; slot(y, x) }"); + assertEval("{ setClass('A0', representation(name = 'character', age = 'numeric')); getSlots('A0') }"); + assertEval("{ setClass('A1', representation(name = 'character', age = 'numeric'), prototype(name = NA_character_, age = NA_real_)); obj <- new('A1', name = 'FastR'); obj@age }"); + assertEval("{ setClass('A2', representation(name = 'character', age = 'numeric')); obj <- new('A2', name = 'FastR'); obj@age }"); + assertEval("{ setClass('A3', representation(name = 'character', age = 'numeric')); obj <- new('A3', name = 'FastR'); slot(obj, 'age') <- 5; obj@age }"); } @Test @@ -64,7 +74,7 @@ public class TestS4 extends TestRBase { assertEval("{ x<-getClass(\"ClassUnionRepresentation\"); slot(x, \"virtual\", check=TRUE)<-TRUE; x@virtual }"); assertEval("{ x<-initialize@valueClass; initialize@valueClass<-\"foo\"; initialize@valueClass<-x }"); - assertEval(Output.IgnoreErrorContext, "{ x<-function() 42; attr(x, \"foo\")<-7; y@foo<-42 }"); + assertEval(Output.IgnoreErrorContext, "{ x<-function() 42; attr(x, \"foo\")<-7; x@foo<-42 }"); assertEval(Output.IgnoreErrorContext, "{ x<-function() 42; attr(x, \"foo\")<-7; slot(y, \"foo\")<-42 }"); assertEval(Output.IgnoreErrorContext, "{ x<-function() 42; attr(x, \"foo\")<-7; y<-asS4(x); y@foo<-42 }"); assertEval(Output.IgnoreErrorContext, "{ x<-NULL; `@<-`(x, foo, \"bar\") }"); @@ -85,15 +95,15 @@ public class TestS4 extends TestRBase { public void testAllocation() { assertEval("{ new(\"numeric\") }"); assertEval("{ setClass(\"foo\", representation(j=\"numeric\")); new(\"foo\", j=42) }"); - assertEval("{ setClass(\"foo\", representation(j=\"numeric\")); typeof(new(\"foo\", j=42)) }"); + assertEval("{ setClass(\"foo\", representation(j=\"numeric\")); new(\"foo\", j='text') }"); + assertEval(Output.IgnoreErrorContext, "{ setClass(\"foo\", representation(j=\"numeric\")); new(\"foo\", inexisting=42) }"); } @Test public void testClassCreation() { - // output slightly different from GNU R even though we use R's "show" method to print it - assertEval(Ignored.OutputFormatting, "{ setClass(\"foo\", representation(j=\"numeric\")); getClass(\"foo\") }"); - + assertEval("{ setClass(\"foo\", representation(j=\"numeric\")); getClass(\"foo\") }"); assertEval("{ setClass(\"foo\"); setClass(\"bar\", representation(j = \"numeric\"), contains = \"foo\"); is.null(getClass(\"foo\")@prototype) }"); + assertEval("{ setClass('foo', contains='standardGeneric'); getClass('foo') }"); } @Test @@ -110,6 +120,19 @@ public class TestS4 extends TestRBase { assertEval("{ setClass(\"foo\"); setMethod(\"diag<-\", \"foo\", function(x, value) 42); removeMethod(\"diag<-\", \"foo\"); removeGeneric(\"diag<-\"); removeClass(\"foo\") }"); + assertEval("{ setClass('A'); setClass('A1', contains = 'A'); setClass('A2', contains = 'A1'); setGeneric('foo', function(a, b) standardGeneric('foo')); setMethod('foo', signature('A1', 'A2'), function(a, b) '1-2'); setMethod('foo', signature('A2', 'A1'), function(a, b) '2-1'); foo(new('A2'), new('A2')) }"); + + assertEval("setGeneric('do.call', signature = c('what', 'args'))"); + + assertEval("{ setClass('A1', representation(a='numeric')); setMethod('length', 'A1', function(x) x@a); obj <- new('A1'); obj@a <- 10; length(obj) }"); + + assertEval("{ setClass('A2', representation(a = 'numeric')); setMethod('rep', 'A2', function(x, a, b, c) { c(x@a, a, b, c) }); setMethod('ifelse', c(yes = 'A2'), function(test, yes, no) print(test)) }"); + } + + @Test + public void testInternalDispatch() { + assertEval("setClass('foo', representation(d='numeric')); setMethod(`$`, signature('foo'), function(x, name) 'FOO'); obj <- new('foo'); obj$asdf"); + } @Test @@ -117,12 +140,36 @@ public class TestS4 extends TestRBase { assertEval("{ standardGeneric(42) }"); assertEval("{ standardGeneric(character()) }"); assertEval("{ standardGeneric(\"\") }"); - assertEval("{ standardGeneric(\"foo\", 42) }"); - assertEval("{ x<-42; class(x)<-character(); standardGeneric(\"foo\", x) }"); + assertEval(Output.IgnoreErrorContext, "{ standardGeneric(\"foo\", 42) }"); + assertEval(Output.IgnoreErrorContext, "{ x<-42; class(x)<-character(); standardGeneric(\"foo\", x) }"); + assertEval("{ setClass('A4', representation(a = 'numeric')); setMethod('[[', 'A4', function(x, i, j, ...) NULL); obj <- new('A4'); obj[[1]] }"); } - @Override - public String getTestDir() { - return "S4"; + @Test + public void testObjectValidity() { + assertEval("{ check <- function(object) length(object@n) == 1; setClass('SingleInt', representation(n = 'numeric'), validity = check); new('SingleInt', n = c(1, 2)) }"); + assertEval("{ check <- function(object) length(object@n) == 1; setClass('SingleInt', representation(n = 'numeric'), validity = check); new('SingleInt', n = 1) }"); + } + + @Test + public void testObjectValueSemantics() { + assertEval("{ setClass('WrappedIntVec', representation(n = 'numeric')); x0 <- new('WrappedIntVec', n = 1); x1 <- x0; x1@n <- 2; x0@n == x1@n }"); + } + + @Test + public void testActiveBindings() { + assertEval("someSymbol0 <- 1; makeActiveBinding('someSymbol0', function(x) { x }, .GlobalEnv)"); + assertEval(Output.IgnoreErrorContext, "lockEnvironment(.GlobalEnv); makeActiveBinding('someSymbol1', function(x) { x }, .GlobalEnv)"); + assertEval("makeActiveBinding('someSymbol2', function(x) { x }, .GlobalEnv); bindingIsActive('someSymbol2', .GlobalEnv)"); + assertEval("bindingIsActive('someSymbol3', .GlobalEnv)"); + assertEval(".Internal(bindingIsActive(as.name('someSymbol4'), .GlobalEnv))"); + assertEval("someSymbol5 <- 0; lockBinding('someSymbol5', .GlobalEnv); makeActiveBinding('someSymbol5', function(x) { x }, .GlobalEnv)"); + assertEval("makeActiveBinding('someSymbol6', function(x) { x }, .GlobalEnv); lockBinding('someSymbol6', .GlobalEnv); makeActiveBinding('someSymbol6', function(x) { print('hello') }, .GlobalEnv)"); + assertEval(Ignored.Unknown, + "makeActiveBinding('someSymbol7', function(x) { if(missing(x)) print('get0') else print('set0') }, .GlobalEnv); someSymbol7; someSymbol7 <- 1; makeActiveBinding('someSymbol7', function(x) { if(missing(x)) print('get1') else print('set1') }, .GlobalEnv); someSymbol7; someSymbol7 <- 1"); + assertEval("makeActiveBinding('someSymbol8', function(x) { print('hello') }, .GlobalEnv); someSymbol9 <- 'world'; print(someSymbol8); print(someSymbol9)"); + assertEval("makeActiveBinding('someSymbol10', function(x) { if(missing(x)) print('get0') else print('set0'); NULL }, .GlobalEnv); someSymbol10; someSymbol10 <- 1; makeActiveBinding('someSymbol10', function(x) { if(missing(x)) print('get1') else print('set1'); NULL }, .GlobalEnv); someSymbol10; someSymbol10 <- 1"); + assertEval("makeActiveBinding('var_a', function(x) { if(missing(x)) { print('get'); return(123) } else { print('set'); return(x) } }, .GlobalEnv); inherits(var_a, 'numeric')"); } + } 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 8d04aedae7d37393be8bb78353d4cf15002c0aa6..1eb1faf9b642b24dbb7711d5c867c97feea8e5bc 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,6 +49,7 @@ 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 @@ -69,6 +70,7 @@ public class TestBase { * See {@link com.oracle.truffle.r.test.builtins.TestTestBase} for examples. */ public enum Output implements TestTrait { + ImprovedErrorContext, // FastR provides a more accurate error context IgnoreErrorContext, // the error context is ignored (e.g., "a+b" vs. "a + b") IgnoreErrorMessage, // the actual error message is ignored IgnoreWarningContext, // the warning context is ignored @@ -76,7 +78,9 @@ public class TestBase { MayIgnoreWarningContext, ContainsReferences, // replaces references in form of 0xbcdef1 for numbers IgnoreWhitespace, // removes all whitespace from the whole output - IgnoreCase; // ignores upper/lower case differences + IgnoreCase, // ignores upper/lower case differences + IgnoreDebugPath, // ignores <path> in debug output like "debug at <path> #..." + IgnoreDebugDepth; // ignores call depth printed by the debugger ("Browse[<call depth>]") @Override public String getName() { @@ -466,8 +470,16 @@ public class TestBase { } // support testing of FastR-only functionality (equivalent GNU R output provided separately) + protected void assertEvalFastR(TestTrait trait1, String input, String gnuROutput) { + evalAndCompare(getAssertEvalFastR(gnuROutput, input), trait1); + } + protected void assertEvalFastR(String input, String gnuROutput) { - evalAndCompare(new String[]{"if (length(grep(\"FastR\", R.Version()$version.string)) != 1) { " + gnuROutput + " } else { " + input + " }"}); + evalAndCompare(getAssertEvalFastR(gnuROutput, input)); + } + + private static String[] getAssertEvalFastR(String gnuROutput, String input) { + return new String[]{"if (length(grep(\"FastR\", R.Version()$version.string)) != 1) { " + gnuROutput + " } else { " + input + " }"}; } /* @@ -591,7 +603,7 @@ public class TestBase { ignored.addAll(Arrays.asList(TestTrait.collect(traits, Ignored.class))); output.addAll(Arrays.asList(TestTrait.collect(traits, Output.class))); context.addAll(Arrays.asList(TestTrait.collect(traits, Context.class))); - containsError = (!FULL_COMPARE_ERRORS && (output.contains(Output.IgnoreErrorContext) || output.contains(Output.IgnoreErrorMessage))); + containsError = (!FULL_COMPARE_ERRORS && (output.contains(Output.IgnoreErrorContext) || output.contains(Output.ImprovedErrorContext) || output.contains(Output.IgnoreErrorMessage))); isIgnored = ignored.size() > 0 ^ (ProcessFailedTests && !(ignored.contains(Ignored.Unstable) || ignored.contains(Ignored.SideEffects))); assert !output.contains(Output.IgnoreWhitespace) || output.size() == 1 : "IgnoreWhitespace trait does not work with any other Output trait"; @@ -607,6 +619,12 @@ public class TestBase { if (output.contains(Output.ContainsReferences)) { return convertReferencesInOutput(out); } + if (output.contains(Output.IgnoreDebugPath)) { + return convertDebugOutput(out); + } + if (output.contains(Output.IgnoreDebugDepth)) { + return removeDebugCallDepth(out); + } return out; } } @@ -730,6 +748,29 @@ public class TestBase { return result; } + private static String convertDebugOutput(String out) { + String prefix = "debug at "; + return removeAllOccurrencesBetween(out, prefix, prefix.length(), "#", 0); + } + + private static String removeDebugCallDepth(String out) { + String prefix = "Browse["; + return removeAllOccurrencesBetween(out, prefix, prefix.length(), "]", 0); + } + + private static String removeAllOccurrencesBetween(String out, String prefix, int prefixOffset, String suffix, int suffixOffset) { + StringBuilder sb = new StringBuilder(out); + + int idxPrefix = -1; + int idxSuffix = -1; + + while ((idxPrefix = sb.indexOf(prefix, idxPrefix + 1)) > 0 && (idxSuffix = sb.indexOf(suffix, idxPrefix)) > idxPrefix) { + sb.replace(idxPrefix + prefixOffset, idxSuffix + suffixOffset, ""); + } + + return sb.toString(); + } + private boolean searchWhiteLists(WhiteList[] whiteLists, String input, String expected, String result, TestTraitsSet testTraits) { if (whiteLists == null) { return false; diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_D.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_D.java new file mode 100644 index 0000000000000000000000000000000000000000..1310bf7bd97f4c7c74930ba6d35f0cd11a073ba4 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_D.java @@ -0,0 +1,40 @@ +/* + * 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.builtins; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestBuiltin_D extends TestBase { + + @Test + public void testD() { + assertEval("(df <- D(expression(x^2*sin(x)), \"x\"));df(0)"); + assertEval("(df <- D(quote(x^2*sin(x)), \"x\"));df(0)"); + assertEval("g<-quote(x^2);(df <- D(g, \"x\"));df(0)"); + assertEval("(df <- D(1, \"x\"));df(0)"); + assertEval("x<-1;(df <- D(x, \"x\"));df(0)"); + assertEval("D(expression(), 'a')"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_La.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_La.java index f6e94d3f58617054287b7adde32772bd9af88a34..62d41240e2cc18d44aaec3a0c5e5a8ca13c12736 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_La.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_La.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. */ @@ -68,8 +68,7 @@ public class TestBuiltin_La extends TestBase { @Test public void testLa9() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(-9.64365076099295, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, -29634.0055320061, -5658.08855789941, 0.0595010632288954, 0.0648032071760975, 0.106336668095848, -0.0279843118999398, 0.0762911857283688, 0.188519899277481, 0.0807096390177039, 0.102801905464379, 0.158474416910002, -0.0969121832135675, -0.0447744343994132, 0.0356414154664858, 0.0276881995456826, -5.08106330417909, 3.14280306547868, 3.64768208463163, 0.0962151262827947, -0.216651778533863, -0.0914289830351174, 0.0855052819309283, -0.0191216590449975, 0.0813861110263642, 0.0607902565035442, 0.00888870310603775, -0.027169916923919, -0.0757761335977742, 0.123401654252917, -0.143330536432624, -0.207390338946085, -0.18719988871654, -0.127596387499216, 1.38045811630541, 0.0118370110620473, 0.00504893180870276, 0.0281684584122627, 0.0338400772620966, 0.0283917504929648, 0.0295082108964754, 0.0323216911133222, 0.00156557534974961, 0.00420042190203468, 0.0261141712698031, 0.00786241202554953, -3.21455025366432, -2.66432733346907, -2.18217405946767, -1.0459324747522, 2.77707906967759, -0.000588115022584812, -0.0784367740030637, -0.0437014732535189, -0.0770692424774911, 0.28985899050302, 0.307089887725235, -0.0219216068215179, -0.00578473481976082, -0.0910180640383319, 0.0166427821996303, -0.725866186311298, -0.943724610301472, -0.197997366006898, -0.255325765345392, -1.99736582726463, 1.22009740929232, -0.000660179745382102, 0.118090770461339, 0.00401505451472504, -0.265276591063721, -0.206368639386371, -0.0413572976755921, 0.0138104665936721, -0.0436723349383677, 0.0904843084594291, -0.103695169473043, 0.0314422837299137, -0.171533212490836, -0.0271695331685966, -0.234884785308008, -0.455412006973628, -0.833981960018826, -0.0497205266764892, -0.00169048456815939, 0.0359873442560765, 0.0111849454624309, 0.0174129325629219, -0.00581471075176227, 0.0183876477886015, -0.0380971980704758, -1.14064686420347, -1.21031412747477, -0.546078284372325, -0.385964209884133, -0.535335872363138, 0.617909299639904, 0.034437791264286, -2.66782912116871, -0.0707120154460491, 0.170259689757997, -0.200116024334743, -0.0120487035676503, -0.00787104751465206, -0.0743232096613527, -0.00206481367828156, -2.28129372840694, -1.27183039972242, -0.162921372163874, 0.194143545128708, 0.405329624202872, -0.0239884453210967, 0.161826508366356, 1.47283157923894, -3.57122150532158, 0.0184573285734211, 0.0768346205272587, -0.00300367200170235, -0.047539037475449, -0.0955077077363865, 0.170580587807138, -2.17759855893389, 2.82091161681306, -0.529126651121425, 0.00648102843720064, -0.227590137804697, 0.429332016819553, 0.315382802791974, -0.0921680424483324, 0.358484158960907, 2.74734594573339, -0.00180797874108619, 0.211048746835586, 0.146553774483952, 0.0892496085418831, 0.02104367339158, -1.4517323726226, 0.428703993666521, -0.198393471445493, -0.178300389025286, -0.0518091667043893, 0.133208332446864, -1.01393441911662, 0.520772381447608, 0.936102434059857, -1.6420319436063, 2.59716822825227, 0.194828402482676, 0.15057424104202, -0.232155536267878, -0.0298159890277092, -0.933256525257383, -1.20515451427884, 0.0125087156504907, 0.421920000319943, 0.452875082015975, -0.655679104390575, 0.284781968418535, 0.643096539054797, 1.38165893036928, 0.447700892848835, -0.482856979100538, 1.73960015308741, 0.115853953901054, 0.107343556163412, -0.0385322695831968, -25.7267715462619, -8.40853040573162, -1.45105839286435, -1.58984152452525, -1.59606771970776, 2.79428919380473, 0.596892611732863, -1.03839368638655, -0.0376487500979583, -0.507302835476536, 0.184174590388395, -0.70905481454677, -3.32884312972433, 0.134236291836065, -0.0993249017707237, -6.94757635469386, 1.58613921242054, 0.195741168102286, 0.638223445194413, 1.07571321411184, 0.659104584950073, 0.199707908602043, -0.565980943574209, -0.967985377031296, -0.112927393875596, -0.934672543429794, 0.198159847509218, 0.275086401661377, 3.44668029704689, -0.05066048099299, -1.65912271156868, -1.17593571026872, -0.20132598039105, -0.42732880950559, -1.20727437557593, 0.102943259109259, -0.697974199306205, 0.103630431164098, -0.0620963660266192, -0.16978912837867, 0.739571733406047, -0.872308493604205, -0.757980967070979, -2.00985526447536, -1.92891236077264), .Dim = c(15L, 15L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15'), c('(Intercept)', 'Weight', 'Cylinders4', 'Cylinders5', 'Cylinders6', 'Cylinders8', 'Cylindersrotary', 'TypeLarge', 'TypeMidsize', 'TypeSmall', 'TypeSporty', 'TypeVan', 'EngineSize', 'DriveTrainFront', 'DriveTrainRear'))), 15L); .Internal(La_chol2inv(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(structure(c(-9.64365076099295, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, -29634.0055320061, -5658.08855789941, 0.0595010632288954, 0.0648032071760975, 0.106336668095848, -0.0279843118999398, 0.0762911857283688, 0.188519899277481, 0.0807096390177039, 0.102801905464379, 0.158474416910002, -0.0969121832135675, -0.0447744343994132, 0.0356414154664858, 0.0276881995456826, -5.08106330417909, 3.14280306547868, 3.64768208463163, 0.0962151262827947, -0.216651778533863, -0.0914289830351174, 0.0855052819309283, -0.0191216590449975, 0.0813861110263642, 0.0607902565035442, 0.00888870310603775, -0.027169916923919, -0.0757761335977742, 0.123401654252917, -0.143330536432624, -0.207390338946085, -0.18719988871654, -0.127596387499216, 1.38045811630541, 0.0118370110620473, 0.00504893180870276, 0.0281684584122627, 0.0338400772620966, 0.0283917504929648, 0.0295082108964754, 0.0323216911133222, 0.00156557534974961, 0.00420042190203468, 0.0261141712698031, 0.00786241202554953, -3.21455025366432, -2.66432733346907, -2.18217405946767, -1.0459324747522, 2.77707906967759, -0.000588115022584812, -0.0784367740030637, -0.0437014732535189, -0.0770692424774911, 0.28985899050302, 0.307089887725235, -0.0219216068215179, -0.00578473481976082, -0.0910180640383319, 0.0166427821996303, -0.725866186311298, -0.943724610301472, -0.197997366006898, -0.255325765345392, -1.99736582726463, 1.22009740929232, -0.000660179745382102, 0.118090770461339, 0.00401505451472504, -0.265276591063721, -0.206368639386371, -0.0413572976755921, 0.0138104665936721, -0.0436723349383677, 0.0904843084594291, -0.103695169473043, 0.0314422837299137, -0.171533212490836, -0.0271695331685966, -0.234884785308008, -0.455412006973628, -0.833981960018826, -0.0497205266764892, -0.00169048456815939, 0.0359873442560765, 0.0111849454624309, 0.0174129325629219, -0.00581471075176227, 0.0183876477886015, -0.0380971980704758, -1.14064686420347, -1.21031412747477, -0.546078284372325, -0.385964209884133, -0.535335872363138, 0.617909299639904, 0.034437791264286, -2.66782912116871, -0.0707120154460491, 0.170259689757997, -0.200116024334743, -0.0120487035676503, -0.00787104751465206, -0.0743232096613527, -0.00206481367828156, -2.28129372840694, -1.27183039972242, -0.162921372163874, 0.194143545128708, 0.405329624202872, -0.0239884453210967, 0.161826508366356, 1.47283157923894, -3.57122150532158, 0.0184573285734211, 0.0768346205272587, -0.00300367200170235, -0.047539037475449, -0.0955077077363865, 0.170580587807138, -2.17759855893389, 2.82091161681306, -0.529126651121425, 0.00648102843720064, -0.227590137804697, 0.429332016819553, 0.315382802791974, -0.0921680424483324, 0.358484158960907, 2.74734594573339, -0.00180797874108619, 0.211048746835586, 0.146553774483952, 0.0892496085418831, 0.02104367339158, -1.4517323726226, 0.428703993666521, -0.198393471445493, -0.178300389025286, -0.0518091667043893, 0.133208332446864, -1.01393441911662, 0.520772381447608, 0.936102434059857, -1.6420319436063, 2.59716822825227, 0.194828402482676, 0.15057424104202, -0.232155536267878, -0.0298159890277092, -0.933256525257383, -1.20515451427884, 0.0125087156504907, 0.421920000319943, 0.452875082015975, -0.655679104390575, 0.284781968418535, 0.643096539054797, 1.38165893036928, 0.447700892848835, -0.482856979100538, 1.73960015308741, 0.115853953901054, 0.107343556163412, -0.0385322695831968, -25.7267715462619, -8.40853040573162, -1.45105839286435, -1.58984152452525, -1.59606771970776, 2.79428919380473, 0.596892611732863, -1.03839368638655, -0.0376487500979583, -0.507302835476536, 0.184174590388395, -0.70905481454677, -3.32884312972433, 0.134236291836065, -0.0993249017707237, -6.94757635469386, 1.58613921242054, 0.195741168102286, 0.638223445194413, 1.07571321411184, 0.659104584950073, 0.199707908602043, -0.565980943574209, -0.967985377031296, -0.112927393875596, -0.934672543429794, 0.198159847509218, 0.275086401661377, 3.44668029704689, -0.05066048099299, -1.65912271156868, -1.17593571026872, -0.20132598039105, -0.42732880950559, -1.20727437557593, 0.102943259109259, -0.697974199306205, 0.103630431164098, -0.0620963660266192, -0.16978912837867, 0.739571733406047, -0.872308493604205, -0.757980967070979, -2.00985526447536, -1.92891236077264), .Dim = c(15L, 15L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15'), c('(Intercept)', 'Weight', 'Cylinders4', 'Cylinders5', 'Cylinders6', 'Cylinders8', 'Cylindersrotary', 'TypeLarge', 'TypeMidsize', 'TypeSmall', 'TypeSporty', 'TypeVan', 'EngineSize', 'DriveTrainFront', 'DriveTrainRear'))), 15L); .Internal(La_chol2inv(argv[[1]], argv[[2]]))"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_SplineCoef.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_SplineCoef.java new file mode 100644 index 0000000000000000000000000000000000000000..07f495341c86766a2368a9fdc7c1f7d05bea13a5 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_SplineCoef.java @@ -0,0 +1,40 @@ +/* + * 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.builtins; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestBuiltin_SplineCoef extends TestBase { + + @Test + public void testSimple() { + assertEval(".Call(stats:::C_SplineCoef, 0, 0, 0)"); + } + + @Test + public void testNull() { + assertEval(".Call(stats:::C_SplineCoef, 0, 0, NULL)"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java index 557d6a7a791d74c8b0a01c1a6f28793124f9b973..b13bdb9886e1b09b9c39a647adc4201f454448ee 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.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. */ @@ -29,8 +29,8 @@ public class TestBuiltin_Syssetlocale extends TestBase { @Test public void testSyssetlocaleInvalidArgs() { - assertEval(Output.IgnoreErrorContext, ".Internal(Sys.setlocale(4, c('more', 'elements')))"); - assertEval(Output.IgnoreErrorContext, ".Internal(Sys.setlocale(4, 42))"); + assertEval(".Internal(Sys.setlocale(4, c('more', 'elements')))"); + assertEval(".Internal(Sys.setlocale(4, 42))"); assertEval(Output.IgnoreErrorMessage, ".Internal(Sys.setlocale('3L', 'C'))"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_abs.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_abs.java index c15b3706a2ea6d0649e0f88665868cd6ec9cd2b2..041fd9ad9053469ab332bc976d239321137c3312 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_abs.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_abs.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -35,8 +35,7 @@ public class TestBuiltin_abs extends TestBase { @Test public void testabs4() { - assertEval(Ignored.Unknown, - "argv <- list(c(0, 0, 0, 0, 0, 1.75368801162502e-134, 0, 0, 0, 2.60477585273833e-251, 1.16485035372295e-260, 0, 1.53160350210786e-322, 0.333331382328728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.44161262707711e-123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.968811545398e-173, 0, 8.2359965384697e-150, 0, 0, 0, 0, 6.51733217171341e-10, 0, 2.36840184577368e-67, 0, 9.4348408357524e-307, 0, 1.59959906013771e-89, 0, 8.73836857865034e-286, 7.09716190970992e-54, 0, 0, 0, 1.530425353017e-274, 8.57590058044551e-14, 0.333333106397154, 0, 0, 1.36895217898448e-199, 2.0226102635783e-177, 5.50445388209462e-42, 0, 0, 0, 0, 1.07846402051283e-44, 1.88605464411243e-186, 1.09156111051203e-26, 0, 3.0702877273237e-124, 0.333333209689785, 0, 0, 0, 0, 0, 0, 3.09816093866831e-94, 0, 0, 4.7522727332095e-272, 0, 0, 2.30093251441394e-06, 0, 0, 1.27082826644707e-274, 0, 0, 0, 0, 0, 0, 0, 4.5662025456054e-65, 0, 2.77995853978268e-149, 0, 0, 0));abs(argv[[1]]);"); + assertEval("argv <- list(c(0, 0, 0, 0, 0, 1.75368801162502e-134, 0, 0, 0, 2.60477585273833e-251, 1.16485035372295e-260, 0, 1.53160350210786e-322, 0.333331382328728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.44161262707711e-123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.968811545398e-173, 0, 8.2359965384697e-150, 0, 0, 0, 0, 6.51733217171341e-10, 0, 2.36840184577368e-67, 0, 9.4348408357524e-307, 0, 1.59959906013771e-89, 0, 8.73836857865034e-286, 7.09716190970992e-54, 0, 0, 0, 1.530425353017e-274, 8.57590058044551e-14, 0.333333106397154, 0, 0, 1.36895217898448e-199, 2.0226102635783e-177, 5.50445388209462e-42, 0, 0, 0, 0, 1.07846402051283e-44, 1.88605464411243e-186, 1.09156111051203e-26, 0, 3.0702877273237e-124, 0.333333209689785, 0, 0, 0, 0, 0, 0, 3.09816093866831e-94, 0, 0, 4.7522727332095e-272, 0, 0, 2.30093251441394e-06, 0, 0, 1.27082826644707e-274, 0, 0, 0, 0, 0, 0, 0, 4.5662025456054e-65, 0, 2.77995853978268e-149, 0, 0, 0));abs(argv[[1]]);"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_all.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_all.java index b656b2072f9acb4bfba25aed04995ae8509a8034..6f66c04a966818b7b4b0f5d739c205b86f02e8ab 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_all.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_all.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -29,7 +29,7 @@ public class TestBuiltin_all extends TestBase { @Test public void testall3() { - assertEval(Output.IgnoreWarningContext, "argv <- list(c(1, 1, 3, 1, 1, 3, 3, 3, 3), FALSE, NULL);all(argv[[1]],argv[[2]],argv[[3]]);"); + assertEval("argv <- list(c(1, 1, 3, 1, 1, 3, 3, 3, 3), FALSE, NULL);all(argv[[1]],argv[[2]],argv[[3]]);"); } @Test @@ -117,10 +117,9 @@ public class TestBuiltin_all extends TestBase { assertEval("{ all(TRUE, TRUE, NA, na.rm=FALSE) }"); assertEval("{ all(TRUE, TRUE, NA, na.rm=TRUE) }"); - // FIXME coercion warning missing assertEval("{ all(1) }"); assertEval("{ all(0) }"); - assertEval(Output.IgnoreWarningContext, "{ all(TRUE,c(TRUE,TRUE),1) }"); + assertEval("{ all(TRUE,c(TRUE,TRUE),1) }"); assertEval("{ all(TRUE,c(TRUE,TRUE),1,0) }"); assertEval("{ all(NULL) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_allnames.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_allnames.java index 54e5ed2846c7ff90c54ebdfbedcf09d4ff29e692..d832fd2ef53902b66b8388e0d6a00f7344122a47 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_allnames.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_allnames.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. */ @@ -64,5 +64,7 @@ public class TestBuiltin_allnames extends TestBase { assertEval("{ all.names(expression(sin(x+y+x)), unique=T) }"); assertEval("{ all.names(expression(sin(x+y+x)), unique=NULL) }"); assertEval("{ all.names(expression(sin(x+y+x)), unique=NA) }"); + + assertEval("{ all.names(quote(switch(x, 'median' =, 'hello' = print('hello case')))) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicated.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicated.java index 4f6b89d198e47d66e8a16d9eebe12740048c4ded..4459a88831f0cda841576e8e6e45931c7019b20a 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicated.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicated.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -153,7 +153,7 @@ public class TestBuiltin_anyDuplicated extends TestBase { assertEval("{ anyDuplicated(c(1+1i, 4-6i, 4-6i, 6+7i)) }"); assertEval("{ anyDuplicated(c(1, 4+6i, 7+7i, 1), incomparables = c(1, 2)) }"); - assertEval(Output.IgnoreWarningContext, "{ anyDuplicated(c(1L, 2L, 1L, 1L, 3L, 2L), incomparables = \"cat\") }"); - assertEval(Output.IgnoreWarningContext, "{ anyDuplicated(c(1,2,3,2), incomparables = c(2+6i)) }"); + assertEval("{ anyDuplicated(c(1L, 2L, 1L, 1L, 3L, 2L), incomparables = \"cat\") }"); + assertEval("{ anyDuplicated(c(1,2,3,2), incomparables = c(2+6i)) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aperm.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aperm.java index a0c32a8668bb5f0fafa6ddc11f34714662ecad51..9bd788df9e25b5e4f3680b76a72e6adde86d5bb5 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aperm.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aperm.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -193,7 +193,7 @@ public class TestBuiltin_aperm extends TestBase { assertEval("{ aperm(array(c('FASTR', 'IS', 'SO', 'FAST'), c(3,1,2))) }"); // perm specified in complex numbers produces warning - assertEval(Output.IgnoreWarningContext, "{ aperm(array(1:27,c(3,3,3)), c(1+1i,3+3i,2+2i))[1,2,3] == array(1:27,c(3,3,3))[1,3,2]; }"); + assertEval("{ aperm(array(1:27,c(3,3,3)), c(1+1i,3+3i,2+2i))[1,2,3] == array(1:27,c(3,3,3))[1,3,2]; }"); // perm is not a permutation vector assertEval("{ aperm(array(1,c( 3,3,3)), c(1,2,1)); }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_array.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_array.java index 4d67fec7e1f7d17db99a127db8f504fd7089a0b8..4a2724063a9a53d83ee45fe2fad6b41b2f315e38 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_array.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_array.java @@ -156,7 +156,7 @@ public class TestBuiltin_array extends TestBase { @Test public void testArray() { assertEval("{ array(1:4, 1:2, 4) }"); - assertEval(Output.IgnoreWarningContext, "{ array(1:4, c(1+2i, 2+2i)) }"); + assertEval("{ array(1:4, c(1+2i, 2+2i)) }"); assertEval("{ array(as.raw(1:4)) }"); assertEval("{ array(1:4, integer()) }"); assertEval("{ array(NULL) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asPOSIXlt.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asPOSIXlt.java index b6cb25016bab4b51ae4f702f7b50d52b48536fc5..eec124843f68e15f9f428b858505bf64deedb105 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asPOSIXlt.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asPOSIXlt.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. */ @@ -71,4 +71,10 @@ public class TestBuiltin_asPOSIXlt extends TestBase { public void testasPOSIXlt11() { assertEval("argv <- list(NULL, ''); .Internal(as.POSIXlt(argv[[1]], argv[[2]]))"); } + + @Test + public void testasPOSIXlt() { + assertEval(Output.MayIgnoreErrorContext, ".Internal(as.POSIXlt(, 1))"); + assertEval(Output.MayIgnoreErrorContext, ".Internal(as.POSIXlt(2, ))"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java index 551890dda835ba3c7345b6594e5993e9160986c6..c14ea94779518649d14ea38c2f50ae62e5c8802c 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java @@ -249,6 +249,7 @@ public class TestBuiltin_ascharacter extends TestBase { @Test public void testAsCharacter() { + assertEval("{ as.character() }"); assertEval("{ as.character(1) }"); assertEval("{ as.character(1L) }"); assertEval("{ as.character(TRUE) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascomplex.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascomplex.java index e8c02db81367dfeafb82b671b8e4771134568f50..7f63eca369365b415e2d414f107f1e5e6cd2f87f 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascomplex.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascomplex.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -74,6 +74,7 @@ public class TestBuiltin_ascomplex extends TestBase { @Test public void testAsComplex() { + assertEval("{ as.complex() }"); assertEval("{ as.complex(0) }"); assertEval("{ as.complex(TRUE) }"); assertEval("{ as.complex(\"1+5i\") }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java index be3fdc04e5c106ffc04ba0c3b82b29936cdcc8b5..8cdead0a43f3d7edb5e26074b8dbc3bba59d6328 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -84,8 +84,7 @@ public class TestBuiltin_asdouble extends TestBase { @Test public void testasdouble14() { - assertEval(Ignored.Unknown, - "argv <- list(c(0, 0, 0, 0, 0, 1.75368801162502e-134, 0, 0, 0, 2.60477585273833e-251, 1.16485035372295e-260, 0, 1.53160350210786e-322, 0.333331382328728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.44161262707712e-123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.96881154539801e-173, 0, 8.23599653846971e-150, 0, 0, 0, 0, 6.51733217171342e-10, 0, 2.36840184577368e-67, 0, 9.43484083575241e-307, 0, 1.59959906013772e-89, 0, 8.73836857865035e-286, 7.09716190970993e-54, 0, 0, 0, 1.530425353017e-274, 8.57590058044552e-14, 0.333333106397154, 0, 0, 1.36895217898448e-199, 2.0226102635783e-177, 5.50445388209462e-42, 0, 0, 0, 0, 1.07846402051283e-44, 1.88605464411243e-186, 1.09156111051203e-26, 0, 3.07028772732371e-124, 0.333333209689785, 0, 0, 0, 0, 0, 0, 3.09816093866831e-94, 0, 0, 4.75227273320951e-272, 0, 0, 2.30093251441394e-06, 0, 0, 1.27082826644707e-274, 0, 0, 0, 0, 0, 0, 0, 4.5662025456054e-65, 0, 2.77995853978268e-149, 0, 0, 0));as.double(argv[[1]]);"); + assertEval("argv <- list(c(0, 0, 0, 0, 0, 1.75368801162502e-134, 0, 0, 0, 2.60477585273833e-251, 1.16485035372295e-260, 0, 1.53160350210786e-322, 0.333331382328728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.44161262707712e-123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.96881154539801e-173, 0, 8.23599653846971e-150, 0, 0, 0, 0, 6.51733217171342e-10, 0, 2.36840184577368e-67, 0, 9.43484083575241e-307, 0, 1.59959906013772e-89, 0, 8.73836857865035e-286, 7.09716190970993e-54, 0, 0, 0, 1.530425353017e-274, 8.57590058044552e-14, 0.333333106397154, 0, 0, 1.36895217898448e-199, 2.0226102635783e-177, 5.50445388209462e-42, 0, 0, 0, 0, 1.07846402051283e-44, 1.88605464411243e-186, 1.09156111051203e-26, 0, 3.07028772732371e-124, 0.333333209689785, 0, 0, 0, 0, 0, 0, 3.09816093866831e-94, 0, 0, 4.75227273320951e-272, 0, 0, 2.30093251441394e-06, 0, 0, 1.27082826644707e-274, 0, 0, 0, 0, 0, 0, 0, 4.5662025456054e-65, 0, 2.77995853978268e-149, 0, 0, 0));as.double(argv[[1]]);"); } @Test @@ -175,6 +174,7 @@ public class TestBuiltin_asdouble extends TestBase { @Test public void testAsDouble() { + assertEval("{ as.double() }"); assertEval("{ as.double(\"1.27\") }"); assertEval("{ as.double(1L) }"); assertEval("{ as.double(as.raw(1)) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asfunction.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asfunction.java index 063819596e5ef87e2dabae41d85b56728fbaa3a5..c58d69b373b9e411d59f76229fee654c7b48ed2c 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asfunction.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asfunction.java @@ -40,7 +40,7 @@ public class TestBuiltin_asfunction extends TestBase { assertEval("{ as.function(alist(\"foo\"))() }"); assertEval("{ as.function(alist(7+42i))() }"); assertEval("{ as.function(alist(as.raw(7)))() }"); - assertEval("{ .Internal(as.function.default(alist(a+b), \"foo\")) }"); + assertEval(Output.IgnoreErrorContext, "{ .Internal(as.function.default(alist(a+b), \"foo\")) }"); assertEval(Output.IgnoreErrorContext, "{ .Internal(as.function.default(function() 42, parent.frame())) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java index dc6b2ebb7ac90798f560f21007f87cbc3592583f..6efaa38af0fc646336bef5e74fa19a7281053daa 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -116,6 +116,7 @@ public class TestBuiltin_asinteger extends TestBase { @Test public void testAsInteger() { + assertEval("{ as.integer() }"); assertEval("{ as.integer(\"1\") }"); assertEval("{ as.integer(c(\"1\",\"2\")) }"); assertEval("{ as.integer(c(1,2,3)) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asmatrix.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asmatrix.java index 5e62c86975ae9d1f84718a5e292bd744202af628..54beac54cc3789b523f4f2b2b8b5832661234a1d 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asmatrix.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asmatrix.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -69,6 +69,8 @@ public class TestBuiltin_asmatrix extends TestBase { assertEval("{ matrix(1:6, nrow=c(3,4,5),byrow=TRUE)}"); assertEval("{ matrix(1:6)}"); assertEval("{ matrix(1:6, ncol=3:5,byrow=TRUE)}"); + assertEval("{ matrix(1:16,2,2)}"); + assertEval("{ matrix(1.1:16.1,2,2)}"); assertEval("{ matrix(TRUE,FALSE,FALSE,TRUE)}"); assertEval("{ matrix(c(NaN,4+5i,2+0i,5+10i)) } "); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asraw.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asraw.java index cd7d0198a34beb1d9641563e31ec0d82da549305..d8c0187dacfb3f77352b69a7d78d97ffad8bf785 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asraw.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asraw.java @@ -49,6 +49,7 @@ public class TestBuiltin_asraw extends TestBase { @Test public void testAsRaw() { + assertEval("{ as.raw() }"); assertEval("{ as.raw(NULL) }"); assertEval("{ as.raw(1) }"); assertEval("{ as.raw(1L) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java index 671161d6d806b1213fdbc8037f30ee9fb5a8aa09..11385e6c408a423f8c3936b2a3948c79b57a19c4 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java @@ -395,16 +395,16 @@ public class TestBuiltin_asvector extends TestBase { @Test public void testAsVector() { - assertEval(Output.IgnoreWarningContext, "{ as.vector(\"foo\", \"integer\") }"); - assertEval(Output.IgnoreWarningContext, "{ as.vector(\"foo\", \"double\") }"); - assertEval(Output.IgnoreWarningContext, "{ as.vector(\"foo\", \"numeric\") }"); + assertEval("{ as.vector(\"foo\", \"integer\") }"); + assertEval("{ as.vector(\"foo\", \"double\") }"); + assertEval("{ as.vector(\"foo\", \"numeric\") }"); assertEval("{ as.vector(\"foo\", \"logical\") }"); - assertEval(Output.IgnoreWarningContext, "{ as.vector(\"foo\", \"raw\") }"); + assertEval("{ as.vector(\"foo\", \"raw\") }"); assertEval("{ as.vector(\"foo\", \"character\") }"); assertEval("{ as.vector(\"foo\", \"list\") }"); assertEval("{ as.vector(\"foo\") }"); - assertEval(Output.IgnoreErrorContext, "{ as.vector(\"foo\", \"bar\") }"); - assertEval(Output.IgnoreWarningContext, "{ as.vector(c(\"foo\", \"bar\"), \"raw\") }"); + assertEval(Output.ImprovedErrorContext, "{ as.vector(\"foo\", \"bar\") }"); + assertEval("{ as.vector(c(\"foo\", \"bar\"), \"raw\") }"); assertEval("x<-c(a=1.1, b=2.2); as.vector(x, \"raw\")"); assertEval("x<-c(a=1L, b=2L); as.vector(x, \"complex\")"); assertEval("{ x<-c(a=FALSE, b=TRUE); attr(x, \"foo\")<-\"foo\"; y<-as.vector(x); attributes(y) }"); @@ -422,9 +422,9 @@ public class TestBuiltin_asvector extends TestBase { assertEval("as.vector(x~z)"); assertEval("as.vector(file(''))"); - assertEval("{ as.vector(42, NULL) }"); - assertEval("{ as.vector(42, c(\"character\", \"character\")) }"); - assertEval("{ as.vector(42, character()) }"); + assertEval(Output.ImprovedErrorContext, "{ as.vector(42, NULL) }"); + assertEval(Output.ImprovedErrorContext, "{ as.vector(42, c(\"character\", \"character\")) }"); + assertEval(Output.ImprovedErrorContext, "{ as.vector(42, character()) }"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan2.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan2.java index ee785542b930ecc1d6d9c3f29c30598053b85026..43a54a0dd24e553d6a21740c39257d2370da0542 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan2.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan2.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -55,8 +55,9 @@ public class TestBuiltin_atan2 extends TestBase { assertEval("{ atan2(c(0.3,0.6,0.9), c(0.4, 0.3)) }"); assertEval("{ atan2() }"); assertEval("{ atan2(0.7) }"); - assertEval("{ atan2(NULL, 1) }"); - assertEval("{ atan2(2, new.env()) }"); - assertEval("{ atan2(2, as.symbol('45')) }"); + + assertEval(Output.ImprovedErrorContext, "{ atan2(NULL, 1) }"); + assertEval(Output.ImprovedErrorContext, "{ atan2(2, new.env()) }"); + assertEval(Output.ImprovedErrorContext, "{ atan2(2, as.symbol('45')) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attach.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attach.java index 9162f204511713221e774dd47c8c21b17d771eac..845dfe6bb6a6724a6f995c3cf437a43ca39c5bba 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attach.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attach.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -40,7 +40,7 @@ public class TestBuiltin_attach extends TestBase { public void testArguments() { assertEval("attach('string')"); assertEval(Output.IgnoreErrorMessage, "attach(list(x=42), pos='string')"); - assertEval(Output.IgnoreErrorContext, "attach(list(), name=42)"); + assertEval("attach(list(), name=42)"); assertEval("detach('string')"); } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attrassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attrassign.java index ab83f538b284c7c7cf469045ea726e1c386b427e..e69737300cb5c637d2e54237b978b172d2824241 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attrassign.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attrassign.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. */ @@ -106,7 +106,7 @@ public class TestBuiltin_attrassign extends TestBase { @Test public void testArgsCasts() { - assertEval(Output.IgnoreErrorContext, "x<-42; attr(x, NULL) <- NULL"); - assertEval(Output.IgnoreErrorContext, "x<-42; attr(x, 42) <- NULL"); + assertEval("x<-42; attr(x, NULL) <- NULL"); + assertEval("x<-42; attr(x, 42) <- NULL"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bincode.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bincode.java index b846256ea75fa4d6d6827fbd93489d2d7ba019ff..15d35bf6b79c2be67e67ea74a4e1d74f3c088716 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bincode.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bincode.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -53,5 +53,11 @@ public class TestBuiltin_bincode extends TestBase { assertEval("{ x <- c(0, 0.01, 0.5, 0.99, 1); b <- c(0, 0, 1, 1); .bincode(x, b, FALSE) }"); assertEval("{ x <- c(0, 0.01, 0.5, 0.99, 1); b <- c(0, 0, 1, 1); .bincode(x, b, TRUE, TRUE) }"); assertEval("{ x <- c(0, 0.01, 0.5, 0.99, 1); b <- c(0, 0, 1, 1); .bincode(x, b, FALSE, TRUE) }"); + + assertEval("{ .Internal(bincode(NULL, 2, T, T)) }"); + assertEval("{ .Internal(bincode(2, NULL, T, T)) }"); + + assertEval(Output.MayIgnoreErrorContext, "{ .Internal(bincode(, 1, T, T)) }"); + assertEval(Output.MayIgnoreErrorContext, "{ .Internal(bincode(1, ,T, T)) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseNot.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseNot.java index 256dbc903893f19a47bd974af0184ce3dac931e5..1f872e33ec385efa606a90a211a881faa092f1f1 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseNot.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseNot.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -27,6 +27,6 @@ public class TestBuiltin_bitwiseNot extends TestBase { assertEval("{ bitwNot(c(17,24,34,48,51,66,72,99)) }"); assertEval("{ bitwNot(c(0,100,200,50,70,20)) }"); - assertEval(Output.IgnoreErrorContext, "{ bitwNot(TRUE) }"); + assertEval("{ bitwNot(TRUE) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftL.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftL.java index 480abb29840f7e8e24970ebbfd98e7724e7fcb35..d62332e72c93da6ec21490bf61041ad8d309db4a 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftL.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftL.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -24,6 +24,8 @@ public class TestBuiltin_bitwiseShiftL extends TestBase { @Test public void testBitwiseFunctions() { + assertEval(Output.MayIgnoreErrorContext, "{ .Internal(bitwiseShiftL(, 1))}"); + assertEval(Output.MayIgnoreErrorContext, "{ .Internal(bitwiseShiftL(200, ))}"); assertEval("{ bitwShiftL(c(10,11,12,13,14,15), c(1,1,1,1,1,1)) }"); assertEval("{ bitwShiftL(c(100,200,300), 1) }"); assertEval("{ bitwShiftL(c(25,57,66), c(10,20,30,40,50,60)) }"); @@ -32,9 +34,7 @@ public class TestBuiltin_bitwiseShiftL extends TestBase { assertEval("{ bitwShiftL(TRUE, c(TRUE, FALSE)) }"); assertEval("{ bitwShiftL(c(3+3i), c(3,2,4)) }"); - // Warning message mismatch - assertEval(Output.IgnoreWarningContext, "{ bitwShiftL(c(3,2,4), c(3+3i)) }"); - // No warning message printed for NAs produced by coercion + assertEval("{ bitwShiftL(c(3,2,4), c(3+3i)) }"); assertEval("{ bitwShiftL(c(1,2,3,4), c(\"a\")) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java index 459a1421dddec339bff3acb18f6736b9d8c23e56..0f441d89da75e23997520e9e2f493ab1385b30ab 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -24,11 +24,13 @@ public class TestBuiltin_bitwiseShiftR extends TestBase { @Test public void testBitwiseFunctions() { + assertEval(Output.MayIgnoreErrorContext, "{ .Internal(bitwiseShiftR(, 1))}"); + assertEval(Output.MayIgnoreErrorContext, "{ .Internal(bitwiseShiftR(200, ))}"); assertEval("{ bitwShiftR(c(10,11,12,13,14,15), c(1,1,1,1,1,1)) }"); assertEval("{ bitwShiftR(c(100,200,300), 1) }"); assertEval("{ bitwShiftR(c(25,57,66), c(10,20,30,40,50,60)) }"); - assertEval(Output.IgnoreWarningContext, "{ bitwShiftR(c(3,2,4), c(3+3i)) }"); + assertEval("{ bitwShiftR(c(3,2,4), c(3+3i)) }"); // No warning message printed for NAs produced by coercion assertEval(Ignored.Unknown, "{ bitwShiftR(c(1,2,3,4), c(\"Hello\")) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_body.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_body.java index 07c7586fac61736687570033fd1771d19dbe0b45..7abf3fc602f04ada2863b9a5df018acf04a43e33 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_body.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_body.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. */ @@ -34,7 +34,7 @@ public class TestBuiltin_body extends TestBase { @Test public void testbody4() { - assertEval(Ignored.Unknown, "argv <- list(.Primitive('/')); .Internal(body(argv[[1]]))"); + assertEval("argv <- list(.Primitive('/')); .Internal(body(argv[[1]]))"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cat.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cat.java index de7b8be16ce93827d27dcd8457bfd5ba43b94404..14c81d803834529b0c355704c9a82fb3710771fe 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cat.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cat.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -91,9 +91,9 @@ public class TestBuiltin_cat extends TestBase { @Test public void testCatUnsupportedArgs() { assertEval("cat(list(), expression(), sep='this-should-be-ok')"); - assertEval("cat(list(1,2,3))"); - assertEval("cat(parse(text='42'))"); + assertEval(Output.ImprovedErrorContext, "cat(list(1,2,3))"); + assertEval(Output.ImprovedErrorContext, "cat(parse(text='42'))"); assertEval("cat(quote(a))"); - assertEval("cat(quote(3+3))"); + assertEval(Output.ImprovedErrorContext, "cat(quote(3+3))"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java index d39f463f15a32fc012ce216b0797e9f95b6d16e2..d675297dfde60ea95f8c542ac019a3b20c5f6fd6 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java @@ -49,6 +49,12 @@ public class TestBuiltin_cbind extends TestBase { "do.call('cbind', argv)"); } + @Test + public void testcbind6() { + assertEval("cbind2(3, 4)"); + assertEval("cbind2(matrix(1:10, 2, 2), matrix(11:20, 2, 2))"); + } + @Test public void testCbind() { assertEval("{ cbind() }"); @@ -62,6 +68,7 @@ public class TestBuiltin_cbind extends TestBase { assertEval("{ cbind(c(1,c=2)) }"); assertEval("{ v<-c(b=1, c=2); cbind(v) }"); assertEval("{ cbind(matrix(1:4, nrow=2, dimnames=list(c('a', 'b'), c('x', 'y')))) }"); + assertEval("{x <- numeric(); y <- matrix(2,2); dimnames(y) <- list(c(NA_character_,NA_character_), c(NA_character_)); rbind(x, y) }"); assertEval("{ cbind(a=c(1,2), b=c(3,4)) }"); assertEval("{ cbind(a=c(x=1,y=2), b=c(3,4)) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_classassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_classassign.java index 4d2c9af5a108b1587540bff0bec573dc8f956b91..28e7365e5ad2e4c0eb0e083f59c6d931092d5b3d 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_classassign.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_classassign.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -126,6 +126,11 @@ public class TestBuiltin_classassign extends TestBase { @Test public void testUpdateClass() { + assertEval(Output.MayIgnoreErrorContext, "{`class<-`(, \"foo\") }"); + assertEval(Output.MayIgnoreErrorContext, "{`class<-`(, ) }"); + assertEval(Output.MayIgnoreErrorContext, "{x=1; `class<-`(x, ) }"); + assertEval(Output.MayIgnoreErrorContext, "{`class<-`(NULL, \"first\") }"); + assertEval("{x=1; class(x)<-\"first\"; x;}"); assertEval("{ x=1;class(x)<-\"character\"; x}"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_copyDFattr.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_copyDFattr.java index f167e67786f25a5717c86d94745856e5e831e5bf..fa5d0bd6d6a24d3564afe1ae31be9de78ca0f93e 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_copyDFattr.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_copyDFattr.java @@ -24,14 +24,12 @@ public class TestBuiltin_copyDFattr extends TestBase { @Test public void testcopyDFattr2() { - assertEval(Output.IgnoreWarningContext, - "argv <- list(structure(list(y = c(2.30923841792462, 3.23011719303818, 2.9161246695212, 3.35931329373059, 5.3777049208621, 5.63518136825043, 7.37725908636056, 7.75621985157329, 10.1175871700049, 8.86877085545769), x1 = 1:10, x2 = 1:10, x3 = c(0.1, 0.4, 0.9, 1.6, 2.5, 3.6, 4.9, 6.4, 8.1, 10)), .Names = c('y', 'x1', 'x2', 'x3'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x1 + x2 + x3)), structure(list(y = NULL, x1 = NULL, x2 = NULL, x3 = NULL), .Names = c('y', 'x1', 'x2', 'x3'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x1 + x2 + x3))); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(structure(list(y = c(2.30923841792462, 3.23011719303818, 2.9161246695212, 3.35931329373059, 5.3777049208621, 5.63518136825043, 7.37725908636056, 7.75621985157329, 10.1175871700049, 8.86877085545769), x1 = 1:10, x2 = 1:10, x3 = c(0.1, 0.4, 0.9, 1.6, 2.5, 3.6, 4.9, 6.4, 8.1, 10)), .Names = c('y', 'x1', 'x2', 'x3'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x1 + x2 + x3)), structure(list(y = NULL, x1 = NULL, x2 = NULL, x3 = NULL), .Names = c('y', 'x1', 'x2', 'x3'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x1 + x2 + x3))); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); } @Test public void testcopyDFattr3() { - assertEval(Output.IgnoreWarningContext, - "argv <- list(structure(list(y = c(-0.0561287395290008, -0.155795506705329, -1.47075238389927, -0.47815005510862, 0.417941560199702, 1.35867955152904, -0.102787727342996, 0.387671611559369, -0.0538050405829051, -1.37705955682861), x = c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE), z = 1:10), .Names = c('y', 'x', 'z'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x * z)), structure(list(y = NULL, x = NULL, z = NULL), .Names = c('y', 'x', 'z'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x * z))); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(structure(list(y = c(-0.0561287395290008, -0.155795506705329, -1.47075238389927, -0.47815005510862, 0.417941560199702, 1.35867955152904, -0.102787727342996, 0.387671611559369, -0.0538050405829051, -1.37705955682861), x = c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE), z = 1:10), .Names = c('y', 'x', 'z'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x * z)), structure(list(y = NULL, x = NULL, z = NULL), .Names = c('y', 'x', 'z'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x * z))); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); } @Test @@ -41,14 +39,12 @@ public class TestBuiltin_copyDFattr extends TestBase { @Test public void testcopyDFattr5() { - assertEval(Output.IgnoreWarningContext, - "argv <- list(structure(list(A = 0:10, B = 10:20, `NA` = 20:30), .Names = c('A', 'B', NA), row.names = c(NA, -11L), class = 'data.frame'), structure(list(A = NULL, B = NULL, `NA` = NULL), .Names = c('A', 'B', NA), row.names = c(NA, -11L), class = 'data.frame')); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(structure(list(A = 0:10, B = 10:20, `NA` = 20:30), .Names = c('A', 'B', NA), row.names = c(NA, -11L), class = 'data.frame'), structure(list(A = NULL, B = NULL, `NA` = NULL), .Names = c('A', 'B', NA), row.names = c(NA, -11L), class = 'data.frame')); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); } @Test public void testcopyDFattr6() { - assertEval(Output.IgnoreWarningContext, - "argv <- list(structure(list(`Surv(stop, status * as.numeric(event), type = 'mstate')` = structure(c(760, 2160, 5441, 277, 1815, 2587, 547, 1125, 2010, 2422, 6155, 1767, 61, 60, 7807, 7732, 6126, 7921, 3590, 5231, 5384, 5934, 6415, 6789, 6778, 3561, 4505, 3987, 4726, 5550, 5216, 5757, 2345, 6931, 6760, 5796, 4810, 5143, 3091, 3316, 700, 1706, 5088, 944, 2466, 1706, 7364, 1857, 9510, 9603, 31, 7479, 2006, 2588, 2983, 8761, 3932, 4201, 5293, 273, 2223, 4249, 5308, 8327, 499, 5789, 7417, 3242, 3275, 10359, 10852, 362, 9993, 1795, 3562, 4139, 4840, 4959, 547, 4119, 8308, 1674, 2953, 3776, 1369, 7911, 7519, 9318, 4370, 7301, 1642, 4169, 7417, 6117, 4536, 7235, 6723, 7397, 7428, 2084, 4066, 1673, 2860, 0, 3773, 4810, 4206, 2314, 4065, 8961, 6143, 517, 3837, 7498, 2815, 8806, 7668, 12457, 8600, 7003, 2435, 1826, 2403, 3805, 4901, 365, 6642, 3318, 3012, 1431, 2223, 4962, 5982, 638, 3346, 4996, 6800, 7454, 8887, 5024, 2833, 4232, 5238, 3186, 3380, 3382, 8100, 1766, 7184, 8059, 6008, 5047, 2236, 8165, 4224, 2844, 6256, 7370, 3560, 4939, 4941, 2230, 3068, 152, 10122, 3226, 3943, 518, 8569, 845, 2099, 8006, 8052, 9560, 0, 7965, 7470, 8133, 809, 153, 1851, 3010, 2121, 7085, 5068, 7093, 5930, 6878, 8080, 791, 6626, 3962, 1116, 1249, 9257, 1077, 566, 174, 4627, 5022, 2070, 3012, 1625, 6607, 8381, 8389, 1005, 3895, 4236, 6970, 8497, 2861, 8487, 3227, 8030, 8023, 31, 2435, 518, 4758, 7958, 7884, 4453, 6349, 7862, 1392, 3167, 6025, 4656, 1767, 7736, 2678, 2191, 3658, 7758, 8009, 2556, 3511, 7954, 822, 4321, 5151, 7545, 7576, 32, 7875, 5236, 7106, 2802, 7898, 3014, 7867, 5354, 2989, 7555, 6089, 8697, 6479, 1826, 5917, 792, 1431, 1434, 4763, 2910, 6209, 5824, 2400, 1400, 3027, 7198, 7247, 2557, 3855, 61, 7410, 1492, 7160, 7899, 5181, 7280, 3448, 7381, 2434, 6763, 7065, 1218, 1554, 7533, 7288, 2922, 5988, 2495, 5234, 9598, 2953, 2961, 4539, 3775, 6524, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 0, 2, 1, 2, 2, 0, 2, 1, 2, 0, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 2, 1, 2, 2, 0, 1, 2, 1, 2, 2, 2, 2, 0, 2, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 2, 1, 2, 2, 1, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 2, 0, 2, 2, 1, 0, 2, 2, 0, 0, 2, 0, 2, 1, 2, 1, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 0, 0, 2, 2, 1, 2, 2, 1, 2, 0, 2, 1, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 1, 2, 1, 2, 2, 0, 2, 2, 2, 0, 2, 2, 1, 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 1, 2, 0, 2, 2, 2, 1, 2, 1, 2, 2, 2, 0, 0, 2, 1, 2, 1, 0, 1, 0, 2, 0, 0, 2, 2, 2, 2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 1, 2, 0, 0, 1, 2, 0, 2, 1, 2, 1, 2, 2, 0, 1, 2, 1, 0, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 0, 0, 1, 2, 2, 0, 2, 0, 2, 2, 0, 2, 0, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 2, 0, 1, 2, 2, 1, 2), .Dim = c(300L, 2L), .Dimnames = list(NULL, c('time', 'status')), type = 'mright', states = c('1', '2'), class = 'Surv')), .Names = 'Surv(stop, status * as.numeric(event), type = \\\'mstate\\\')', class = 'data.frame', row.names = c(NA, 300L)), structure(list(`Surv(stop, status * as.numeric(event), type = 'mstate')` = NULL), .Names = 'Surv(stop, status * as.numeric(event), type = \\\'mstate\\\')', class = 'data.frame', row.names = c(NA, 300L))); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(structure(list(`Surv(stop, status * as.numeric(event), type = 'mstate')` = structure(c(760, 2160, 5441, 277, 1815, 2587, 547, 1125, 2010, 2422, 6155, 1767, 61, 60, 7807, 7732, 6126, 7921, 3590, 5231, 5384, 5934, 6415, 6789, 6778, 3561, 4505, 3987, 4726, 5550, 5216, 5757, 2345, 6931, 6760, 5796, 4810, 5143, 3091, 3316, 700, 1706, 5088, 944, 2466, 1706, 7364, 1857, 9510, 9603, 31, 7479, 2006, 2588, 2983, 8761, 3932, 4201, 5293, 273, 2223, 4249, 5308, 8327, 499, 5789, 7417, 3242, 3275, 10359, 10852, 362, 9993, 1795, 3562, 4139, 4840, 4959, 547, 4119, 8308, 1674, 2953, 3776, 1369, 7911, 7519, 9318, 4370, 7301, 1642, 4169, 7417, 6117, 4536, 7235, 6723, 7397, 7428, 2084, 4066, 1673, 2860, 0, 3773, 4810, 4206, 2314, 4065, 8961, 6143, 517, 3837, 7498, 2815, 8806, 7668, 12457, 8600, 7003, 2435, 1826, 2403, 3805, 4901, 365, 6642, 3318, 3012, 1431, 2223, 4962, 5982, 638, 3346, 4996, 6800, 7454, 8887, 5024, 2833, 4232, 5238, 3186, 3380, 3382, 8100, 1766, 7184, 8059, 6008, 5047, 2236, 8165, 4224, 2844, 6256, 7370, 3560, 4939, 4941, 2230, 3068, 152, 10122, 3226, 3943, 518, 8569, 845, 2099, 8006, 8052, 9560, 0, 7965, 7470, 8133, 809, 153, 1851, 3010, 2121, 7085, 5068, 7093, 5930, 6878, 8080, 791, 6626, 3962, 1116, 1249, 9257, 1077, 566, 174, 4627, 5022, 2070, 3012, 1625, 6607, 8381, 8389, 1005, 3895, 4236, 6970, 8497, 2861, 8487, 3227, 8030, 8023, 31, 2435, 518, 4758, 7958, 7884, 4453, 6349, 7862, 1392, 3167, 6025, 4656, 1767, 7736, 2678, 2191, 3658, 7758, 8009, 2556, 3511, 7954, 822, 4321, 5151, 7545, 7576, 32, 7875, 5236, 7106, 2802, 7898, 3014, 7867, 5354, 2989, 7555, 6089, 8697, 6479, 1826, 5917, 792, 1431, 1434, 4763, 2910, 6209, 5824, 2400, 1400, 3027, 7198, 7247, 2557, 3855, 61, 7410, 1492, 7160, 7899, 5181, 7280, 3448, 7381, 2434, 6763, 7065, 1218, 1554, 7533, 7288, 2922, 5988, 2495, 5234, 9598, 2953, 2961, 4539, 3775, 6524, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 0, 2, 1, 2, 2, 0, 2, 1, 2, 0, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 2, 1, 2, 2, 0, 1, 2, 1, 2, 2, 2, 2, 0, 2, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 2, 1, 2, 2, 1, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 2, 0, 2, 2, 1, 0, 2, 2, 0, 0, 2, 0, 2, 1, 2, 1, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 0, 0, 2, 2, 1, 2, 2, 1, 2, 0, 2, 1, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 1, 2, 1, 2, 2, 0, 2, 2, 2, 0, 2, 2, 1, 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 1, 2, 0, 2, 2, 2, 1, 2, 1, 2, 2, 2, 0, 0, 2, 1, 2, 1, 0, 1, 0, 2, 0, 0, 2, 2, 2, 2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 1, 2, 0, 0, 1, 2, 0, 2, 1, 2, 1, 2, 2, 0, 1, 2, 1, 0, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 0, 0, 1, 2, 2, 0, 2, 0, 2, 2, 0, 2, 0, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 2, 0, 1, 2, 2, 1, 2), .Dim = c(300L, 2L), .Dimnames = list(NULL, c('time', 'status')), type = 'mright', states = c('1', '2'), class = 'Surv')), .Names = 'Surv(stop, status * as.numeric(event), type = \\\'mstate\\\')', class = 'data.frame', row.names = c(NA, 300L)), structure(list(`Surv(stop, status * as.numeric(event), type = 'mstate')` = NULL), .Names = 'Surv(stop, status * as.numeric(event), type = \\\'mstate\\\')', class = 'data.frame', row.names = c(NA, 300L))); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); } @Test @@ -75,14 +71,12 @@ public class TestBuiltin_copyDFattr extends TestBase { @Test public void testcopyDFattr11() { - assertEval(Output.IgnoreWarningContext, - "argv <- list(structure(list(srcfile = c(NA, '/home/lzhao/hg/r-instrumented/library/stats/R/stats', '/home/lzhao/hg/r-instrumented/library/stats/R/stats', '/home/lzhao/hg/r-instrumented/library/stats/R/stats'), frow = c(NA, 2228L, 2369L, 2379L), lrow = c(NA, 2228L, 2369L, 2380L)), .Names = c('srcfile', 'frow', 'lrow'), row.names = c(NA, 4L), class = 'data.frame'), structure(list(srcfile = NULL, frow = NULL, lrow = NULL), .Names = c('srcfile', 'frow', 'lrow'), row.names = c(NA, 4L), class = 'data.frame')); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(structure(list(srcfile = c(NA, '/home/lzhao/hg/r-instrumented/library/stats/R/stats', '/home/lzhao/hg/r-instrumented/library/stats/R/stats', '/home/lzhao/hg/r-instrumented/library/stats/R/stats'), frow = c(NA, 2228L, 2369L, 2379L), lrow = c(NA, 2228L, 2369L, 2380L)), .Names = c('srcfile', 'frow', 'lrow'), row.names = c(NA, 4L), class = 'data.frame'), structure(list(srcfile = NULL, frow = NULL, lrow = NULL), .Names = c('srcfile', 'frow', 'lrow'), row.names = c(NA, 4L), class = 'data.frame')); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); } @Test public void testcopyDFattr12() { - assertEval(Output.IgnoreWarningContext, - "argv <- list(structure(list(y = c(73, 73, 70, 74, 75, 115, 105, 107, 124, 107, 116, 125, 102, 144, 178, 149, 177, 124, 157, 128, 169, 165, 186, 152, 181, 139, 173, 151, 138, 181, 152, 188, 173, 196, 180, 171, 188, 174, 198, 172, 176, 162, 188, 182, 182, 141, 191, 190, 159, 170, 163, 197), x = c(1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 11, 12)), .Names = c('y', 'x'), class = 'data.frame', row.names = c(NA, 52L), terms = quote(~y + x)), structure(list(y = NULL, x = NULL), .Names = c('y', 'x'), class = 'data.frame', row.names = c(NA, 52L), terms = quote(~y + x))); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(structure(list(y = c(73, 73, 70, 74, 75, 115, 105, 107, 124, 107, 116, 125, 102, 144, 178, 149, 177, 124, 157, 128, 169, 165, 186, 152, 181, 139, 173, 151, 138, 181, 152, 188, 173, 196, 180, 171, 188, 174, 198, 172, 176, 162, 188, 182, 182, 141, 191, 190, 159, 170, 163, 197), x = c(1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 11, 12)), .Names = c('y', 'x'), class = 'data.frame', row.names = c(NA, 52L), terms = quote(~y + x)), structure(list(y = NULL, x = NULL), .Names = c('y', 'x'), class = 'data.frame', row.names = c(NA, 52L), terms = quote(~y + x))); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); } @Test @@ -93,32 +87,27 @@ public class TestBuiltin_copyDFattr extends TestBase { @Test public void testcopyDFattr14() { - assertEval(Output.IgnoreWarningContext, - "argv <- list(structure(list(y = c(-0.667819876370237, 0.170711734013213, 0.552921941721332, -0.253162069270378, -0.00786394222146348, 0.0246733498130512, 0.0730305465518564, -1.36919169254062, 0.0881443844426084, -0.0834190388782434)), .Names = 'y', class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ 0)), structure(list(y = NULL), .Names = 'y', class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ 0))); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(structure(list(y = c(-0.667819876370237, 0.170711734013213, 0.552921941721332, -0.253162069270378, -0.00786394222146348, 0.0246733498130512, 0.0730305465518564, -1.36919169254062, 0.0881443844426084, -0.0834190388782434)), .Names = 'y', class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ 0)), structure(list(y = NULL), .Names = 'y', class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ 0))); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); } @Test public void testcopyDFattr15() { - assertEval(Output.IgnoreWarningContext, - "argv <- list(structure(list(`cbind(w = weight, w2 = weight^2)` = structure(c(4.17, 5.58, 5.18, 6.11, 4.5, 4.61, 5.17, 4.53, 5.33, 5.14, 4.81, 4.17, 4.41, 3.59, 5.87, 3.83, 6.03, 4.89, 4.32, 4.69, 17.3889, 31.1364, 26.8324, 37.3321, 20.25, 21.2521, 26.7289, 20.5209, 28.4089, 26.4196, 23.1361, 17.3889, 19.4481, 12.8881, 34.4569, 14.6689, 36.3609, 23.9121, 18.6624, 21.9961), .Dim = c(20L, 2L), .Dimnames = list(NULL, c('w', 'w2'))), group = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c('Ctl', 'Trt'), class = 'factor')), .Names = c('cbind(w = weight, w2 = weight^2)', 'group'), class = 'data.frame', row.names = c(NA, 20L), terms = quote(cbind(w = weight, w2 = weight^2) ~ group)), structure(list(`cbind(w = weight, w2 = weight^2)` = NULL, group = NULL), .Names = c('cbind(w = weight, w2 = weight^2)', 'group'), class = 'data.frame', row.names = c(NA, 20L), terms = quote(cbind(w = weight, w2 = weight^2) ~ group))); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(structure(list(`cbind(w = weight, w2 = weight^2)` = structure(c(4.17, 5.58, 5.18, 6.11, 4.5, 4.61, 5.17, 4.53, 5.33, 5.14, 4.81, 4.17, 4.41, 3.59, 5.87, 3.83, 6.03, 4.89, 4.32, 4.69, 17.3889, 31.1364, 26.8324, 37.3321, 20.25, 21.2521, 26.7289, 20.5209, 28.4089, 26.4196, 23.1361, 17.3889, 19.4481, 12.8881, 34.4569, 14.6689, 36.3609, 23.9121, 18.6624, 21.9961), .Dim = c(20L, 2L), .Dimnames = list(NULL, c('w', 'w2'))), group = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c('Ctl', 'Trt'), class = 'factor')), .Names = c('cbind(w = weight, w2 = weight^2)', 'group'), class = 'data.frame', row.names = c(NA, 20L), terms = quote(cbind(w = weight, w2 = weight^2) ~ group)), structure(list(`cbind(w = weight, w2 = weight^2)` = NULL, group = NULL), .Names = c('cbind(w = weight, w2 = weight^2)', 'group'), class = 'data.frame', row.names = c(NA, 20L), terms = quote(cbind(w = weight, w2 = weight^2) ~ group))); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); } @Test public void testcopyDFattr16() { - assertEval(Output.IgnoreWarningContext, - "argv <- list(structure(list(Y = c(130L, 157L, 174L, 117L, 114L, 161L, 141L, 105L, 140L, 118L, 156L, 61L, 91L, 97L, 100L, 70L, 108L, 126L, 149L, 96L, 124L, 121L, 144L, 68L, 64L, 112L, 86L, 60L, 102L, 89L, 96L, 89L, 129L, 132L, 124L, 74L, 89L, 81L, 122L, 64L, 103L, 132L, 133L, 70L, 89L, 104L, 117L, 62L, 90L, 100L, 116L, 80L, 82L, 94L, 126L, 63L, 70L, 109L, 99L, 53L, 74L, 118L, 113L, 89L, 82L, 86L, 104L, 97L, 99L, 119L, 121L), B = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L), .Label = c('I', 'II', 'III', 'IV', 'V', 'VI'), class = 'factor'), V = structure(c(3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), .Label = c('Golden.rain', 'Marvellous', 'Victory'), class = 'factor'), N = structure(c(2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c('0.0cwt', '0.2cwt', '0.4cwt', '0.6cwt'), class = 'factor')), .Names = c('Y', 'B', 'V', 'N'), terms = quote(Y ~ B + V + N + V:N), row.names = 2:72, class = 'data.frame'), structure(list(Y = NULL, B = NULL, V = NULL, N = NULL), .Names = c('Y', 'B', 'V', 'N'), terms = quote(Y ~ B + V + N + V:N), row.names = 2:72, class = 'data.frame')); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(structure(list(Y = c(130L, 157L, 174L, 117L, 114L, 161L, 141L, 105L, 140L, 118L, 156L, 61L, 91L, 97L, 100L, 70L, 108L, 126L, 149L, 96L, 124L, 121L, 144L, 68L, 64L, 112L, 86L, 60L, 102L, 89L, 96L, 89L, 129L, 132L, 124L, 74L, 89L, 81L, 122L, 64L, 103L, 132L, 133L, 70L, 89L, 104L, 117L, 62L, 90L, 100L, 116L, 80L, 82L, 94L, 126L, 63L, 70L, 109L, 99L, 53L, 74L, 118L, 113L, 89L, 82L, 86L, 104L, 97L, 99L, 119L, 121L), B = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L), .Label = c('I', 'II', 'III', 'IV', 'V', 'VI'), class = 'factor'), V = structure(c(3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), .Label = c('Golden.rain', 'Marvellous', 'Victory'), class = 'factor'), N = structure(c(2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c('0.0cwt', '0.2cwt', '0.4cwt', '0.6cwt'), class = 'factor')), .Names = c('Y', 'B', 'V', 'N'), terms = quote(Y ~ B + V + N + V:N), row.names = 2:72, class = 'data.frame'), structure(list(Y = NULL, B = NULL, V = NULL, N = NULL), .Names = c('Y', 'B', 'V', 'N'), terms = quote(Y ~ B + V + N + V:N), row.names = 2:72, class = 'data.frame')); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); } @Test public void testcopyDFattr17() { - assertEval(Output.IgnoreWarningContext, - "argv <- list(structure(list(Fr = c(32, 53, 10, 3, 11, 50, 10, 30, 10, 25, 7, 5, 3, 15, 7, 8, 36, 66, 16, 4, 9, 34, 7, 64, 5, 29, 7, 5, 2, 14, 7, 8), Hair = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c('Black', 'Brown', 'Red', 'Blond'), class = 'factor'), Eye = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L), .Label = c('Brown', 'Blue', 'Hazel', 'Green'), class = 'factor'), Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c('Male', 'Female'), class = 'factor')), .Names = c('Fr', 'Hair', 'Eye', 'Sex'), class = 'data.frame', row.names = c(NA, 32L), terms = quote(Fr ~ (Hair + Eye + Sex)^2)), structure(list(Fr = NULL, Hair = NULL, Eye = NULL, Sex = NULL), .Names = c('Fr', 'Hair', 'Eye', 'Sex'), class = 'data.frame', row.names = c(NA, 32L), terms = quote(Fr ~ (Hair + Eye + Sex)^2))); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(structure(list(Fr = c(32, 53, 10, 3, 11, 50, 10, 30, 10, 25, 7, 5, 3, 15, 7, 8, 36, 66, 16, 4, 9, 34, 7, 64, 5, 29, 7, 5, 2, 14, 7, 8), Hair = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c('Black', 'Brown', 'Red', 'Blond'), class = 'factor'), Eye = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L), .Label = c('Brown', 'Blue', 'Hazel', 'Green'), class = 'factor'), Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c('Male', 'Female'), class = 'factor')), .Names = c('Fr', 'Hair', 'Eye', 'Sex'), class = 'data.frame', row.names = c(NA, 32L), terms = quote(Fr ~ (Hair + Eye + Sex)^2)), structure(list(Fr = NULL, Hair = NULL, Eye = NULL, Sex = NULL), .Names = c('Fr', 'Hair', 'Eye', 'Sex'), class = 'data.frame', row.names = c(NA, 32L), terms = quote(Fr ~ (Hair + Eye + Sex)^2))); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); } @Test public void testcopyDFattr18() { - assertEval(Output.IgnoreWarningContext, - "argv <- list(structure(list(Employed = c(60.323, 61.122, 60.171, 61.187, 63.221, 63.639, 64.989, 63.761, 66.019, 67.857, 68.169, 66.513, 68.655, 69.564, 69.331, 70.551), GNP.deflator = c(83, 88.5, 88.2, 89.5, 96.2, 98.1, 99, 100, 101.2, 104.6, 108.4, 110.8, 112.6, 114.2, 115.7, 116.9), GNP = c(234.289, 259.426, 258.054, 284.599, 328.975, 346.999, 365.385, 363.112, 397.469, 419.18, 442.769, 444.546, 482.704, 502.601, 518.173, 554.894), Unemployed = c(235.6, 232.5, 368.2, 335.1, 209.9, 193.2, 187, 357.8, 290.4, 282.2, 293.6, 468.1, 381.3, 393.1, 480.6, 400.7), Armed.Forces = c(159, 145.6, 161.6, 165, 309.9, 359.4, 354.7, 335, 304.8, 285.7, 279.8, 263.7, 255.2, 251.4, 257.2, 282.7), Population = c(107.608, 108.632, 109.773, 110.929, 112.075, 113.27, 115.094, 116.219, 117.388, 118.734, 120.445, 121.95, 123.366, 125.368, 127.852, 130.081), Year = 1947:1962), .Names = c('Employed', 'GNP.deflator', 'GNP', 'Unemployed', 'Armed.Forces', 'Population', 'Year'), class = 'data.frame', row.names = 1947:1962, terms = quote(Employed ~ GNP.deflator + GNP + Unemployed + Armed.Forces + Population + Year)), structure(list(Employed = NULL, GNP.deflator = NULL, GNP = NULL, Unemployed = NULL, Armed.Forces = NULL, Population = NULL, Year = NULL), .Names = c('Employed', 'GNP.deflator', 'GNP', 'Unemployed', 'Armed.Forces', 'Population', 'Year'), class = 'data.frame', row.names = 1947:1962, terms = quote(Employed ~ GNP.deflator + GNP + Unemployed + Armed.Forces + Population + Year))); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(structure(list(Employed = c(60.323, 61.122, 60.171, 61.187, 63.221, 63.639, 64.989, 63.761, 66.019, 67.857, 68.169, 66.513, 68.655, 69.564, 69.331, 70.551), GNP.deflator = c(83, 88.5, 88.2, 89.5, 96.2, 98.1, 99, 100, 101.2, 104.6, 108.4, 110.8, 112.6, 114.2, 115.7, 116.9), GNP = c(234.289, 259.426, 258.054, 284.599, 328.975, 346.999, 365.385, 363.112, 397.469, 419.18, 442.769, 444.546, 482.704, 502.601, 518.173, 554.894), Unemployed = c(235.6, 232.5, 368.2, 335.1, 209.9, 193.2, 187, 357.8, 290.4, 282.2, 293.6, 468.1, 381.3, 393.1, 480.6, 400.7), Armed.Forces = c(159, 145.6, 161.6, 165, 309.9, 359.4, 354.7, 335, 304.8, 285.7, 279.8, 263.7, 255.2, 251.4, 257.2, 282.7), Population = c(107.608, 108.632, 109.773, 110.929, 112.075, 113.27, 115.094, 116.219, 117.388, 118.734, 120.445, 121.95, 123.366, 125.368, 127.852, 130.081), Year = 1947:1962), .Names = c('Employed', 'GNP.deflator', 'GNP', 'Unemployed', 'Armed.Forces', 'Population', 'Year'), class = 'data.frame', row.names = 1947:1962, terms = quote(Employed ~ GNP.deflator + GNP + Unemployed + Armed.Forces + Population + Year)), structure(list(Employed = NULL, GNP.deflator = NULL, GNP = NULL, Unemployed = NULL, Armed.Forces = NULL, Population = NULL, Year = NULL), .Names = c('Employed', 'GNP.deflator', 'GNP', 'Unemployed', 'Armed.Forces', 'Population', 'Year'), class = 'data.frame', row.names = 1947:1962, terms = quote(Employed ~ GNP.deflator + GNP + Unemployed + Armed.Forces + Population + Year))); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); } @Test @@ -129,8 +118,7 @@ public class TestBuiltin_copyDFattr extends TestBase { @Test public void testcopyDFattr20() { - assertEval(Output.IgnoreWarningContext, - "argv <- list(structure(list(`cbind(X, M)` = structure(c(68, 42, 37, 24, 66, 33, 47, 23, 63, 29, 57, 19, 42, 30, 52, 43, 50, 23, 55, 47, 53, 27, 49, 29), .Dim = c(12L, 2L), .Dimnames = list(NULL, c('X', 'M'))), M.user = structure(c(1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L), .Label = c('N', 'Y'), class = 'factor'), Temp = structure(c(2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L), .Label = c('High', 'Low'), class = 'factor'), Soft = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L), .Label = c('Hard', 'Medium', 'Soft'), class = 'factor')), .Names = c('cbind(X, M)', 'M.user', 'Temp', 'Soft'), class = 'data.frame', row.names = c('1', '3', '5', '7', '9', '11', '13', '15', '17', '19', '21', '23'), terms = quote(cbind(X, M) ~ M.user + Temp + Soft)), structure(list(`cbind(X, M)` = NULL, M.user = NULL, Temp = NULL, Soft = NULL), .Names = c('cbind(X, M)', 'M.user', 'Temp', 'Soft'), class = 'data.frame', row.names = c('1', '3', '5', '7', '9', '11', '13', '15', '17', '19', '21', '23'), terms = quote(cbind(X, M) ~ M.user + Temp + Soft))); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(structure(list(`cbind(X, M)` = structure(c(68, 42, 37, 24, 66, 33, 47, 23, 63, 29, 57, 19, 42, 30, 52, 43, 50, 23, 55, 47, 53, 27, 49, 29), .Dim = c(12L, 2L), .Dimnames = list(NULL, c('X', 'M'))), M.user = structure(c(1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L), .Label = c('N', 'Y'), class = 'factor'), Temp = structure(c(2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L), .Label = c('High', 'Low'), class = 'factor'), Soft = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L), .Label = c('Hard', 'Medium', 'Soft'), class = 'factor')), .Names = c('cbind(X, M)', 'M.user', 'Temp', 'Soft'), class = 'data.frame', row.names = c('1', '3', '5', '7', '9', '11', '13', '15', '17', '19', '21', '23'), terms = quote(cbind(X, M) ~ M.user + Temp + Soft)), structure(list(`cbind(X, M)` = NULL, M.user = NULL, Temp = NULL, Soft = NULL), .Names = c('cbind(X, M)', 'M.user', 'Temp', 'Soft'), class = 'data.frame', row.names = c('1', '3', '5', '7', '9', '11', '13', '15', '17', '19', '21', '23'), terms = quote(cbind(X, M) ~ M.user + Temp + Soft))); .Internal(copyDFattr(argv[[1]], argv[[2]]))"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_crossprod.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_crossprod.java index 254279ebb8bcc3f96c97ee32296d35610a578764..74a1c7a8e1c20bb7bdfa5d8849aa3a8ea159f4a5 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_crossprod.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_crossprod.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -69,5 +69,7 @@ public class TestBuiltin_crossprod extends TestBase { assertEval("{ x <- matrix(c(NaN,2,3,4,5,NA), nrow=3); crossprod(x) }"); assertEval(Ignored.Unknown, "{ x <- matrix(c(NaN,2+3i,3,4+1i,5,NA), nrow=3); crossprod(x) }"); + + assertEval(Output.ImprovedErrorContext, "{ crossprod('asdf', matrix(1:6, ncol=2)) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java index 70eb09d7837341c519da3734844e11d30cc5d755..41c068ab4ad3c20f8c4a383cb09192b1b70eba58 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java @@ -21,6 +21,10 @@ import com.oracle.truffle.r.test.TestBase; // Checkstyle: stop line length check public class TestBuiltin_deparse extends TestBase { + private void assertEvalDeparsed(String snippet) { + assertEval(Output.IgnoreWhitespace, "cat({" + snippet + "})"); + } + @Test public void testdeparse1() { assertEval("argv <- list(quote(rsp), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); @@ -53,7 +57,7 @@ public class TestBuiltin_deparse extends TestBase { @Test public void testdeparse7() { - assertEval(Ignored.Unknown, + assertEvalDeparsed( "argv <- list(quote(y ~ ((g1) * exp((log(g2/g1)) * (1 - exp(-k * (x - Ta)))/(1 - exp(-k * (Tb - Ta)))))), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } @@ -114,7 +118,7 @@ public class TestBuiltin_deparse extends TestBase { @Test public void testdeparse19() { - assertEval(Ignored.Unknown, + assertEvalDeparsed( "argv <- list(structure(list(Sex = structure(c(2L, 2L, 1L, 1L, 2L, 2L), .Label = c('Female', 'Male'), class = 'factor'), age = c(15, 20, 10, 12, 2, 4), Subject = structure(c(2L, 2L, 1L, 1L, 3L, 3L), .Label = c('F30', 'M01', 'M04'), class = 'factor')), .Names = c('Sex', 'age', 'Subject'), row.names = c(NA, -6L), class = 'data.frame'), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } @@ -140,7 +144,7 @@ public class TestBuiltin_deparse extends TestBase { @Test public void testdeparse24() { - assertEval(Ignored.Unknown, + assertEvalDeparsed( "argv <- list(c(7.4, 8, 12.6, 11.5, 14.3, 14.9, 8.6, 13.8, 20.1, 8.6, 6.9, 9.7, 9.2, 10.9, 13.2, 11.5, 12, 18.4, 11.5, 9.7, 9.7, 16.6, 9.7, 12, 16.6, 14.9, 8, 12, 14.9, 5.7, 7.4, 8.6, 9.7, 16.1, 9.2, 8.6, 14.3, 9.7, 6.9, 13.8, 11.5, 10.9, 9.2, 8, 13.8, 11.5, 14.9, 20.7, 9.2, 11.5, 10.3, 6.3, 1.7, 4.6, 6.3, 8, 8, 10.3, 11.5, 14.9, 8, 6.9, 13.8, 7.4, 6.9, 7.4, 4.6, 4, 10.3, 8, 8.6, 11.5, 11.5, 11.5, 9.7, 11.5, 10.3, 6.3, 7.4, 10.9, 10.3, 15.5, 14.3, 12.6, 9.7, 3.4, 8, 5.7, 9.7, 2.3, 6.3, 6.3, 6.9, 5.1, 2.8, 4.6, 7.4, 15.5, 10.9, 10.3, 10.9, 9.7, 14.9, 15.5, 6.3, 10.9, 11.5, 6.9, 13.8, 10.3, 10.3, 8, 12.6, 9.2, 10.3, 10.3, 16.6, 6.9, 13.2, 14.3, 8, 11.5), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } @@ -151,7 +155,7 @@ public class TestBuiltin_deparse extends TestBase { @Test public void testdeparse26() { - assertEval(Ignored.Unknown, + assertEvalDeparsed( "argv <- list(structure(list(distance = c(26, 25, 29, 31, 21.5, 22.5), age = c(8, 10, 12, 14, 8, 10), Subject = structure(c(2L, 2L, 2L, 2L, 1L, 1L), .Label = c('M02', 'M01'), class = c('ordered', 'factor')), Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L), .Label = c('Male', 'Female'), class = 'factor')), .Names = c('distance', 'age', 'Subject', 'Sex'), row.names = c('1', '2', '3', '4', '5', '6'), class = 'data.frame'), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } @@ -177,13 +181,13 @@ public class TestBuiltin_deparse extends TestBase { @Test public void testdeparse31() { - assertEval(Ignored.Unknown, + assertEvalDeparsed( "argv <- list(c(0, 0.587785252292473, 0.951056516295154, 0.951056516295154, 0.587785252292473, 1.22464679914735e-16, -0.587785252292473, -0.951056516295154, -0.951056516295154, -0.587785252292473, -2.44929359829471e-16, 0.587785252292473, 0.951056516295154), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } @Test public void testdeparse32() { - assertEval(Ignored.Unknown, + assertEvalDeparsed( "argv <- list(structure(c(39.384847580955, 40.3469409309138, 42.6018205723052, 46.6665176252597, 51.3438205965467, 60.0069972599329, 64.6480892875058, 62.5709232928432, 57.679739382496, 49.5060394945433, 43.474726406114, 39.8236314289602, 38.361391396627, 37.9275637097922, 43.6868952734483, 45.1919846859641, 51.722520194987, 59.3399821539983, 61.9345241730145, 62.1515308754468, 57.6561604617486, 49.2849925780811, 42.606775772378, 39.6394677676018, 38.6328048791077, 38.4418602988203, 43.1520834957543, 45.6551746936999, 51.7999631155049, 59.5021948495759, 62.9217123388139, 62.0751910659837, 57.8048619656866, 49.5091658164884, 42.8045075272742, 40.2515159054665), .Tsp = c(1937, 1939.91666666667, 12), class = 'ts'), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } @@ -199,7 +203,7 @@ public class TestBuiltin_deparse extends TestBase { @Test public void testdeparse35() { - assertEval(Ignored.Unknown, + assertEvalDeparsed( "argv <- list(structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, 140, 145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166, 171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194, 196, 196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201, 204, 188, 235, 227, 234, 264, 302, 293, 259, 229, 203, 229, 242, 233, 267, 269, 270, 315, 364, 347, 312, 274, 237, 278, 284, 277, 317, 313, 318, 374, 413, 405, 355, 306, 271, 306, 315, 301, 356, 348, 355, 422, 465, 467, 404, 347, 305, 336, 340, 318, 362, 348, 363, 435, 491, 505, 404, 359, 310, 337, 360, 342, 406, 396, 420, 472, 548, 559, 463, 407, 362, 405, 417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390, 432, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 419.147602949539, 391.474665943444, 435.919286153217, 443.935203034261, 455.023399013445, 517.28707821144, 589.71337277669, 582.999919227301, 484.573388713116, 428.878182738437, 368.526582998452, 406.728709993152, 415.660571294428, 388.716535970235, 433.006017658935, 440.885684396326, 451.651900136866, 513.051252429496, 584.327164324967, 577.055407135124, 479.076505013118, 423.494870357491, 363.43932958967, 400.592058645117, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 484.030717075782, 462.954959541421, 526.353307750503, 546.165638262644, 569.502470928676, 657.838443307596, 761.241730163307, 763.280655335144, 642.989004951864, 576.423799567567, 501.429012064338, 559.981301364233, 591.700754553767, 565.210772316967, 642.377841008703, 666.682421047093, 695.547100430962, 804.065022775202, 931.340589597203, 934.837830059897, 788.422986194072, 707.666678543854, 616.37838266375, 689.250456425465), .Dim = c(168L, 3L), .Dimnames = list(NULL, c('structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, ', 'structure(c(419.147602949539, 391.474665943444, 435.919286153217, ', 'structure(c(484.030717075782, 462.954959541421, 526.353307750503, ')), .Tsp = c(1949, 1962.91666666667, 12), class = c('mts', 'ts', 'matrix')), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } @@ -215,8 +219,7 @@ public class TestBuiltin_deparse extends TestBase { @Test public void testdeparse38() { - assertEval(Ignored.Unknown, - "argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = structure('integer(0)', .Names = 'c0')), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); + assertEval("argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = structure('integer(0)', .Names = 'c0')), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } @Test @@ -226,7 +229,7 @@ public class TestBuiltin_deparse extends TestBase { @Test public void testdeparse40() { - assertEval(Output.IgnoreWarningContext, "argv <- list(logical(0), logical(0), FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); + assertEval("argv <- list(logical(0), logical(0), FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } @Test @@ -246,7 +249,7 @@ public class TestBuiltin_deparse extends TestBase { @Test public void testdeparse44() { - assertEval(Ignored.Unknown, + assertEvalDeparsed( "argv <- list(quote(lm(formula = 1000/MPG.city ~ Weight + Cylinders + Type + EngineSize + DriveTrain, data = Cars93)), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } @@ -287,7 +290,7 @@ public class TestBuiltin_deparse extends TestBase { public void testDeparse() { assertEval(template("deparse(%0)", VALUES)); assertEval(template("deparse(quote(cat(%0)))", VALUES)); - assertEval(Ignored.OutputFormatting, "deparse(1.53160350210786e-322)"); + assertEval("deparse(1.53160350210786e-322)"); assertEval("{ deparse(new.env()) }"); assertEval("{ k <- 2 ; deparse(k) }"); assertEval("{ deparse(round) }"); @@ -312,6 +315,10 @@ public class TestBuiltin_deparse extends TestBase { assertEval("{ x<-c(a=42, b=7); deparse(x) }"); assertEval("deparse(quote(1/0))"); + + assertEval("e <- quote(a <- 1); e[[3]] <- as.raw(c(1,6,9,254)); e"); + + assertEval("deparse(list(`x y`=1))"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java new file mode 100644 index 0000000000000000000000000000000000000000..3dcdec562dc272a329ddc5016aba3bd67cd42e27 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java @@ -0,0 +1,201 @@ +/* + * 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.builtins; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; +import com.oracle.truffle.r.test.TestTrait; + +public class TestBuiltin_deriv extends TestBase { + + final class DerivExpr { + final String expr; + final String assertedExpr; + final int dn; + final boolean hessian; + + DerivExpr(String expr, int dn) { + this(expr, dn, false); + } + + DerivExpr(String expr, int dn, boolean hessian) { + this.expr = expr; + this.dn = dn; + this.hessian = hessian; + String vars = dn == 1 ? "c(\"x\")" : "c(\"x\",\"y\")"; + String h = hessian ? "TRUE" : "FALSE"; + this.assertedExpr = "deriv(~ " + expr + ", " + vars + ", hessian=" + h + ")"; + } + + DerivEval derive() { + assertEval(assertedExpr); + return new DerivEval(this); + } + + DerivEval derive(TestTrait trait) { + assertEval(trait, assertedExpr); + return new DerivEval(this); + } + } + + final class DerivEval { + final DerivExpr de; + final String assertedExpr; + + DerivEval(DerivExpr de) { + this.de = de; + String vars = de.dn == 1 ? "x<-%s" : "x<-%s; y<-%s"; + this.assertedExpr = "df <- " + de.assertedExpr + "; " + vars + "; eval(df)"; + } + + DerivEval eval(Object... vals) { + String ex = String.format(this.assertedExpr, vals); + assertEval(ex); + return this; + } + + DerivEval eval(TestTrait trait, Object... vals) { + String ex = String.format(this.assertedExpr, vals); + assertEval(trait, ex); + return this; + } + + DerivExpr withHessian() { + return new DerivExpr(de.expr, de.dn, true); + } + } + + private DerivExpr deriv1(String expr) { + return new DerivExpr(expr, 1); + } + + private DerivExpr deriv2(String expr) { + return new DerivExpr(expr, 2); + } + + private void assertDerivAndEval1(String expr) { + deriv1(expr).derive().eval(0).withHessian().derive().eval(0); + } + + private void assertDerivAndEval1(TestTrait trait, String expr) { + deriv1(expr).derive(trait).eval(0, 0); + } + + private DerivEval assertDeriv1(String expr) { + return deriv1(expr).derive(); + } + + private void assertDerivAndEval2(String expr) { + deriv2(expr).derive().eval(0, 0).withHessian().derive().eval(0, 0); + } + + @Test + public void testDeriveBasicExpressions1() { + assertDerivAndEval1("1"); + assertDerivAndEval1("x"); + assertDerivAndEval1("x+1"); + assertDerivAndEval1("2*x"); + assertDerivAndEval1("x/2"); + assertDerivAndEval1(Ignored.OutputFormatting, "2/x"); + assertDerivAndEval1("x^2"); + assertDerivAndEval1("(x+1)+(x+2)"); + assertDerivAndEval1("(x+1)-(x+2)"); + assertDerivAndEval1("-(x+1)+(x+2)"); + assertDerivAndEval1("-(x+1)-(x+2)"); + assertDerivAndEval1("(x+1)*(x+2)"); + deriv1("(x+1)/(x+2)").derive().eval(0).withHessian().derive(Output.IgnoreWhitespace).eval(0); + assertDerivAndEval1("(x+1)*(x+2*(x-1))"); + assertDerivAndEval1(Ignored.OutputFormatting, "(x+1)^(x+2)"); + } + + @Test + public void testDeriveFunctions1() { + deriv1("log(x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0).eval(1).eval(-1); + assertDerivAndEval1("exp(x)"); + assertDerivAndEval1("cos(x)"); + assertDerivAndEval1("sin(x)"); + assertDerivAndEval1("tan(x)"); + assertDerivAndEval1("cosh(x)"); + assertDerivAndEval1("sinh(x)"); + deriv1("tanh(x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0).eval(1).eval(-1); + assertDerivAndEval1("sqrt(x)"); + deriv1("pnorm(x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0); + assertDerivAndEval1(Ignored.OutputFormatting, "dnorm(x)"); + assertDerivAndEval1("asin(x)"); + assertDerivAndEval1(Ignored.OutputFormatting, "acos(x)"); + deriv1("atan(x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0); + assertDeriv1("gamma(x)").eval(0); + assertDeriv1("lgamma(x)").eval(0.5); + assertDeriv1("digamma(x)").eval(Ignored.Unimplemented, 0); + assertDeriv1("trigamma(x)").eval(Ignored.Unimplemented, 0); + assertDeriv1("psigamma(x)").eval(Ignored.Unimplemented, 0); + } + + @Test + public void testDeriveFunctionsWithCompArg1() { + deriv1("log(2*x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0); + deriv1("log(sin(2*x))").derive().eval(0).withHessian().derive(Output.IgnoreWhitespace).eval(0); + assertDerivAndEval1(Output.IgnoreWhitespace, "log(sin(2*x)*cos(x^2))"); + assertDerivAndEval1(Output.IgnoreWhitespace, "pnorm(sin(2*x)^log(x+1))"); + } + + @Test + public void testDeriveBasicExpressions2() { + assertDerivAndEval2("x + y"); + deriv2("x*y").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0); + deriv2("2*x*y").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0); + deriv2("x/y/2").derive(Ignored.OutputFormatting).eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0); + deriv2("2/x*y").derive(Ignored.OutputFormatting).eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0); + deriv2("x^y").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0); + deriv2("(x+1)*(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0); + assertDerivAndEval2("(x+1)-(y+2)"); + deriv2("-(x+1)+(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0); + deriv2("-(x+1)-(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0); + deriv2("(x+1)/(y+2)").derive(Ignored.OutputFormatting).eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0); + deriv2("(x+1)*(y+2*(x-1))").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0); + deriv2("(x+1)^(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0).eval(1, 1); + } + + @Test + public void testLongExpression() { + deriv2("(log(2*x)+sin(x))*cos(y^x*(exp(x)))*(x*y+x^y/(x+y+1))").derive(Output.IgnoreWhitespace).eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0); + } + + @Test + public void testFunctionGenereration() { + assertEval(Output.IgnoreWhitespace, "(df <- deriv(~x^2*sin(x), \"x\", function.arg=TRUE));df(0)"); + assertEval(Output.IgnoreWhitespace, "(df <- deriv(~x^2*sin(x), \"x\", function.arg=c(\"x\")));df(0)"); + assertEval(Output.IgnoreWhitespace, "(df <- deriv(~x^2*sin(x), \"x\", function.arg=function(x=1){}));df(0)"); + } + + @Test + public void testUnusualExprs() { + assertEval("(df <- deriv(expression(x^2*sin(x)), \"x\"));df(0)"); + assertEval("(df <- deriv(quote(x^2*sin(x)), \"x\"));df(0)"); + assertEval("g<-quote(x^2);(df <- deriv(g, \"x\"));df(0)"); + assertEval("(df <- deriv(1, \"x\"));df(0)"); + assertEval("x<-1;(df <- deriv(x, \"x\"));df(0)"); + } + +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dfltWarn.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dfltWarn.java index 1b21fd0bc0cd63e857130ac537af14babad43074..d21234fe96471e13a6cebad04372079b44f6e35b 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dfltWarn.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dfltWarn.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. */ @@ -24,8 +24,7 @@ public class TestBuiltin_dfltWarn extends TestBase { @Test public void testdfltWarn2() { - assertEval(Output.IgnoreWarningContext, - "argv <- list('bessel_y(2,nu=288.12): precision lost in result', quote(besselY(2, nu = nu <- seq(3, 300, len = 51)))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))"); + assertEval("argv <- list('bessel_y(2,nu=288.12): precision lost in result', quote(besselY(2, nu = nu <- seq(3, 300, len = 51)))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))"); } @Test @@ -35,8 +34,7 @@ public class TestBuiltin_dfltWarn extends TestBase { @Test public void testdfltWarn4() { - assertEval(Output.IgnoreWarningContext, - "argv <- list('header and col.names are of different lengths', quote(read.table('foo3', header = TRUE, col.names = letters[1:4]))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))"); + assertEval("argv <- list('header and col.names are of different lengths', quote(read.table('foo3', header = TRUE, col.names = letters[1:4]))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))"); } @Test @@ -51,7 +49,7 @@ public class TestBuiltin_dfltWarn extends TestBase { @Test public void testdfltWarn7() { - assertEval(Output.IgnoreWarningContext, "argv <- list(\'drop argument will be ignored', quote(`[.data.frame`(women, 'height', drop = FALSE))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(\'drop argument will be ignored', quote(`[.data.frame`(women, 'height', drop = FALSE))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))"); } @Test @@ -62,13 +60,12 @@ public class TestBuiltin_dfltWarn extends TestBase { @Test public void testdfltWarn9() { - assertEval(Output.IgnoreWarningContext, "argv <- list('1 y value <= 0 omitted from logarithmic plot', quote(xy.coords(x, NULL, log = log))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))"); + assertEval("argv <- list('1 y value <= 0 omitted from logarithmic plot', quote(xy.coords(x, NULL, log = log))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))"); } @Test public void testdfltWarn10() { - assertEval(Output.IgnoreWarningContext, - "argv <- list(\'x is neither a vector nor a matrix: using as.numeric(x)', quote(dotchart(table(infert$education)))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(\'x is neither a vector nor a matrix: using as.numeric(x)', quote(dotchart(table(infert$education)))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))"); } @Test @@ -79,7 +76,6 @@ public class TestBuiltin_dfltWarn extends TestBase { @Test public void testdfltWarn12() { - assertEval(Output.IgnoreWarningContext, - "argv <- list('incomplete final line found by readTableHeader on foo4', quote(read.table('foo4', header = TRUE))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))"); + assertEval("argv <- list('incomplete final line found by readTableHeader on foo4', quote(read.table('foo4', header = TRUE))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dput.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dput.java index 0ee4403023b8d66ab9991baaacb9ccfe4c1e83d1..69579bb31dba7937638e94b55dcc2d22e82b3b84 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dput.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dput.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. */ @@ -44,8 +44,7 @@ public class TestBuiltin_dput extends TestBase { @Test public void testdput6() { - assertEval(Ignored.Unimplemented, - "argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = structure('integer(0)', .Names = 'c0')), structure(1L, class = c('terminal', 'connection')), 69); .Internal(dput(argv[[1]], argv[[2]], argv[[3]]))"); + assertEval("argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = structure('integer(0)', .Names = 'c0')), structure(1L, class = c('terminal', 'connection')), 69); .Internal(dput(argv[[1]], argv[[2]], argv[[3]]))"); } @Test @@ -57,4 +56,10 @@ public class TestBuiltin_dput extends TestBase { public void testdput8() { assertEval("argv <- list(c(0.00508571428571428, 0.876285714285715), structure(1L, class = c('terminal', 'connection')), 69); .Internal(dput(argv[[1]], argv[[2]], argv[[3]]))"); } + + @Test + public void testdput() { + assertEval(Output.IgnoreWhitespace, + "x <- structure(list(A = c(1L, 1L), B = structure(c(1L, 1L), .Label = c('G', 'D'), class = 'factor'), C = structure(c(1L, 1L), .Label = c('G', 'D'), class = 'factor')), .Names = c('A', 'B', 'C'), row.names = 1:2, class = 'data.frame'); dput(x)"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_duplicated.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_duplicated.java index 3040237600c6d490b85893e20465e5eec7e6755f..7fd5356776e2ccb9606c7983640136cae71b433e 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_duplicated.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_duplicated.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -126,8 +126,8 @@ public class TestBuiltin_duplicated extends TestBase { assertEval("{ duplicated(c(1+1i, 4-6i, 4-6i, 6+7i)) }"); assertEval("{ duplicated(c(1, 4+6i, 7+7i, 1), incomparables = c(1, 2)) }"); - assertEval(Output.IgnoreWarningContext, "{ duplicated(c(1L, 2L, 1L, 1L, 3L, 2L), incomparables = \"cat\") }"); - assertEval(Output.IgnoreWarningContext, "{ duplicated(c(1,2,3,2), incomparables = c(2+6i)) }"); + assertEval("{ duplicated(c(1L, 2L, 1L, 1L, 3L, 2L), incomparables = \"cat\") }"); + assertEval("{ duplicated(c(1,2,3,2), incomparables = c(2+6i)) }"); assertEval("{ duplicated(NULL, 0); }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_environmentassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_environmentassign.java index af8ec8a7f429a83153e298e6e3d2ab61a2259548..d68f1fea4855854cfd94dfd2c0d684387cb19231 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_environmentassign.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_environmentassign.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. */ @@ -32,5 +32,9 @@ public class TestBuiltin_environmentassign extends TestBase { assertEval("{ f <- function() x; f2 <- f; e <- new.env(); assign('x', 2, envir=e); x <- 1; environment(f) <- e; c(f(), f2())}"); assertEval("{ f <- NULL; environment(f) <- new.env() }"); + + // changing the environment must not change metadata + assertEval("{ f <- asS4(function(x) x+1); r <- isS4(f); environment(f) <- new.env(); r && isS4(f) }"); + assertEval("{ jh <- function(x) x+1; attributes(jh) <- list(myMetaData ='hello'); environment(jh) <- new.env(); attr(jh, 'myMetaData') }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java index a87bc5a7482c9ab5cd1b0bae20b0a1edc405465a..d1b9210eb8a4806f224ceb5c0a09bc3912f25a14 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -60,4 +60,10 @@ public class TestBuiltin_eval extends TestBase { assertEval("a <- 1; lang <- quote(list(a)); eval(lang, new.env(), new.env())"); assertEval(Output.IgnoreErrorMessage, "y <- 2; x <- 2 ; eval(quote(x+y), c(-1, -2))"); } + + @Test + public void testReturnInEvalExpr() { + assertEval("f1 <- function(x) { eval(quote(if(x>2){return()}else 1)); 10 };f1(5);f1(0)"); + } + } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_exp.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_exp.java index 9093f0b0e0e97b1b8b4ec23fe784afcb51c9812d..86d353663c85e1f27a633026c47a538d7b99aeed 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_exp.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_exp.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -64,7 +64,7 @@ public class TestBuiltin_exp extends TestBase { @Test public void testexp11() { - assertEval(Ignored.Unknown, "argv <- list(c(-745, -744, -743, -742, -741, -740, -730, -720, -710, -709, -708, -707, -706, -705));exp(argv[[1]]);"); + assertEval("argv <- list(c(-745, -744, -743, -742, -741, -740, -730, -720, -710, -709, -708, -707, -706, -705));exp(argv[[1]]);"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_dataframe.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_dataframe.java index 306597da00c78fe613982f77adfa90d6ebd6b2dc..d078eccb011520c2bef36c18d3ac1b05776fa145 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_dataframe.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_dataframe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -58,8 +58,6 @@ public class TestBuiltin_extract_dataframe extends TestBase { @Test public void extractDataFrameWithNULLNames() { assertEval("{ fr <- data.frame(1:3,4:6); attr(fr,'names') <- NULL; fr[1,2] }"); - // N.B.: this warning is surprisingly formatted with extra new line before the contents of - // warning(...) invoked from R code - assertEval(Output.IgnoreWarningContext, "{ fr <- data.frame(1:3,4:6); attr(fr,'names') <- NULL; fr['col'] }"); + assertEval("{ fr <- data.frame(1:3,4:6); attr(fr,'names') <- NULL; fr['col'] }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_replace.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_replace.java index f841282b012391086fc26223296274ea5b1128be..3745256f0428282c4d0cd11142617b333cfdd409 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_replace.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_replace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -42,4 +42,10 @@ public class TestBuiltin_extract_replace extends TestBase { public void replaceInLanguagePreservesAttributes() { assertEval("f <- quote(a+b); attr(f, 'mya') <- 42; f[[2]] <- quote(q); f"); } + + @Test + public void replaceExpressionInLanguage() { + assertEval("e1 <- expression(x^2); l1 <- quote(y^2); l1[1] <- e1; l1[[1]]==e1[[1]]"); + assertEval(Ignored.OutputFormatting, "e1 <- expression(x^2); l1 <- quote(y^2); l1[1] <- e1; l1"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_factor.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_factor.java index d6b89595d8626c1d7dfec667483396396efa34f7..85b20fc02ccbe02f941747a50d91ca386d6a1822 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_factor.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_factor.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -38,8 +38,8 @@ public class TestBuiltin_factor extends TestBase { assertEval(Output.IgnoreErrorContext, "{ x<-factor(c(\"a\", \"b\", \"a\")); attr(x, \"levels\")<-NULL; as.character(x) }"); assertEval(Output.IgnoreErrorContext, "{ x<-factor(c(\"a\", \"b\", \"a\")); attr(x, \"levels\")<-character(); as.character(x) }"); - assertEval(Output.IgnoreErrorContext, "{ x<-c(1,2,3); class(x)<-\"factor\"; x }"); - assertEval(Output.IgnoreErrorContext, "{ x<-c(\"1\",\"2\",\"3\"); class(x)<-\"factor\"; x }"); + assertEval("{ x<-c(1,2,3); class(x)<-\"factor\"; x }"); + assertEval("{ x<-c(\"1\",\"2\",\"3\"); class(x)<-\"factor\"; x }"); assertEval(Output.IgnoreErrorContext, "{ x<-c(1L,2L,3L); class(x)<-\"factor\"; x }"); assertEval(Output.IgnoreErrorContext, "{ x<-factor(c(\"a\", \"b\", \"a\")); attr(x, \"levels\")<-c(7L, 42L); x }"); @@ -62,8 +62,8 @@ public class TestBuiltin_factor extends TestBase { assertEval("{ x<-c(1L, 2L, 1L); class(x)<-c(\"ordered\", \"factor\"); levels(x)<-c(\"a\", \"b\"); x > \"a\" }"); - assertEval(Output.IgnoreWarningContext, "{ x<-factor(c(\"c\", \"b\", \"a\", \"c\")); y<-list(1); y[1]<-x; y }"); - assertEval(Output.IgnoreWarningContext, "{ x<-factor(c(\"c\", \"b\", \"a\", \"c\")); y<-c(1); y[1]<-x; y }"); + assertEval("{ x<-factor(c(\"c\", \"b\", \"a\", \"c\")); y<-list(1); y[1]<-x; y }"); + assertEval("{ x<-factor(c(\"c\", \"b\", \"a\", \"c\")); y<-c(1); y[1]<-x; y }"); assertEval("{ x<-factor(c(\"c\", \"b\", \"a\", \"c\")); y<-list(1); y[[1]]<-x; y }"); assertEval("{ x<-factor(c(\"c\", \"b\", \"a\", \"c\")); y<-c(1); y[[1]]<-x; y }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fileinfo.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fileinfo.java index 8f25d9475f6fb7f206e06a6ddf5e5dfa13e86cfd..9802cd410ef9a5375e4688294866cd8c94e13164 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fileinfo.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fileinfo.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. */ @@ -19,11 +19,11 @@ public class TestBuiltin_fileinfo extends TestBase { @Test public void testfileinfo1() { - assertEval(Ignored.Unknown, "argv <- list('/home/lzhao/hg/r-instrumented/library/codetools/data'); .Internal(file.info(argv[[1]]))"); + assertEval("argv <- list('/home/lzhao/hg/r-instrumented/library/codetools/data'); .Internal(file.info(argv[[1]]))"); } @Test public void testfileinfo2() { - assertEval(Ignored.Unknown, "argv <- list(character(0)); .Internal(file.info(argv[[1]]))"); + assertEval("argv <- list(character(0)); .Internal(file.info(argv[[1]]))"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_format.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_format.java index d783aa1d15d5436a5548a211a07b20f9e9ec8603..c426128a20ebfc0bddddf0ba0f309337c5c31fcf 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_format.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_format.java @@ -19,7 +19,7 @@ public class TestBuiltin_format extends TestBase { @Test public void testformat1() { - assertEval(Ignored.Unknown, + assertEval(Output.IgnoreErrorMessage, "argv <- list(structure(c(0, 72.7, 56.4, 72.7, 0, 63.3, 56.4, 63.3, 0), .Dim = c(3L, 3L), .Dimnames = list(c('Girth', 'Height', 'Volume'), c('Girth', 'Height', 'Volume'))), FALSE, 7L, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]], , argv[[9]]))"); } @@ -30,14 +30,12 @@ public class TestBuiltin_format extends TestBase { @Test public void testformat3() { - assertEval(Ignored.Unknown, - "argv <- list(c('Inf', '-Inf', 'NaN', 'NA'), FALSE, NULL, 0L, 4, 1L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(c('Inf', '-Inf', 'NaN', 'NA'), FALSE, NULL, 0L, 4, 1L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test public void testformat4() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c('axx', 'b', 'c', 'd', 'e', 'f', 'g', 'h'), .Dim = c(2L, 4L)), FALSE, NULL, 0L, NULL, 1L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(structure(c('axx', 'b', 'c', 'd', 'e', 'f', 'g', 'h'), .Dim = c(2L, 4L)), FALSE, NULL, 0L, NULL, 1L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test @@ -47,8 +45,7 @@ public class TestBuiltin_format extends TestBase { @Test public void testformat7() { - assertEval(Ignored.Unknown, - "argv <- list(c('a', 'NA', NA, 'b'), FALSE, NULL, 0L, NULL, 0L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(c('a', 'NA', NA, 'b'), FALSE, NULL, 0L, NULL, 0L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test @@ -73,8 +70,7 @@ public class TestBuiltin_format extends TestBase { @Test public void testformat12() { - assertEval(Ignored.Unknown, - "argv <- list(c('Min.', '1st Qu.', 'Median', 'Mean', '3rd Qu.', 'Max.'), FALSE, NULL, 0L, NULL, 0L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(c('Min.', '1st Qu.', 'Median', 'Mean', '3rd Qu.', 'Max.'), FALSE, NULL, 0L, NULL, 0L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test @@ -84,14 +80,12 @@ public class TestBuiltin_format extends TestBase { @Test public void testformat14() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(NA, 1, 1, 1), .Names = c('<none>', '- x4', '- x2', '- x1')), FALSE, 5L, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(structure(c(NA, 1, 1, 1), .Names = c('<none>', '- x4', '- x2', '- x1')), FALSE, 5L, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test public void testformat15() { - assertEval(Ignored.Unknown, - "argv <- list(2.22044604925031e-16, FALSE, 1, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(2.22044604925031e-16, FALSE, 1, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test @@ -121,14 +115,12 @@ public class TestBuiltin_format extends TestBase { @Test public void testformat23() { - assertEval(Ignored.Unknown, - "argv <- list(c(NA, 2L, 4L, 7L), FALSE, NULL, 0L, NULL, 3L, FALSE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(c(NA, 2L, 4L, 7L), FALSE, NULL, 0L, NULL, 3L, FALSE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test public void testformat24() { - assertEval(Ignored.Unknown, - "argv <- list(c(1.1+0i, NA, 3+0i), FALSE, NULL, 0L, NULL, 3L, FALSE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(c(1.1+0i, NA, 3+0i), FALSE, NULL, 0L, NULL, 3L, FALSE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test @@ -143,26 +135,22 @@ public class TestBuiltin_format extends TestBase { @Test public void testformat27() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(142L, 104L, 71L, 250L), .Dim = 4L, .Dimnames = structure(list(c('(1) Approve STRONGLY', '(2) Approve SOMEWHAT', '(3) Disapprove SOMEWHAT', '(4) Disapprove STRONGLY')), .Names = '')), FALSE, 7L, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(structure(c(142L, 104L, 71L, 250L), .Dim = 4L, .Dimnames = structure(list(c('(1) Approve STRONGLY', '(2) Approve SOMEWHAT', '(3) Disapprove SOMEWHAT', '(4) Disapprove STRONGLY')), .Names = '')), FALSE, 7L, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test public void testformat28() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c('***', '*', ' ', ' ', ' '), legend = '0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1', class = 'noquote'), FALSE, NULL, 0L, NULL, 0L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(structure(c('***', '*', ' ', ' ', ' '), legend = '0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1', class = 'noquote'), FALSE, NULL, 0L, NULL, 0L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test public void testformat29() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(0, 5, 118, 57, 0, 1, 4, 140, 0, 11, 154, 14, 0, 13, 13, 80, 35, 13, 387, 75, 17, 14, 89, 76, 0, 0, 670, 192, 0, 0, 3, 20), .Dim = c(1L, 32L), row.vars = structure(list(), .Names = character(0)), col.vars = structure(list(Class = c('1st', '2nd', '3rd', 'Crew'), Sex = c('Male', 'Female'), Age = c('Child', 'Adult'), Survived = c('No', 'Yes')), .Names = c('Class', 'Sex', 'Age', 'Survived'))), FALSE, 7L, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(structure(c(0, 5, 118, 57, 0, 1, 4, 140, 0, 11, 154, 14, 0, 13, 13, 80, 35, 13, 387, 75, 17, 14, 89, 76, 0, 0, 670, 192, 0, 0, 3, 20), .Dim = c(1L, 32L), row.vars = structure(list(), .Names = character(0)), col.vars = structure(list(Class = c('1st', '2nd', '3rd', 'Crew'), Sex = c('Male', 'Female'), Age = c('Child', 'Adult'), Survived = c('No', 'Yes')), .Names = c('Class', 'Sex', 'Age', 'Survived'))), FALSE, 7L, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test public void testformat30() { - assertEval(Ignored.Unknown, - "argv <- list(c('', '', '\\\'Adult\\\'', '\\\'No\\\'', '', '387'), FALSE, NULL, 0L, NULL, 1L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(c('', '', '\\\'Adult\\\'', '\\\'No\\\'', '', '387'), FALSE, NULL, 0L, NULL, 1L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test @@ -172,8 +160,7 @@ public class TestBuiltin_format extends TestBase { @Test public void testformat32() { - assertEval(Ignored.Unknown, - "argv <- list(c(-0.318309886183791+0i, 0-0.564189583547756i, 1+0i, 0+1.77245385090552i, -3.14159265358979+0i), TRUE, 2, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(c(-0.318309886183791+0i, 0-0.564189583547756i, 1+0i, 0+1.77245385090552i, -3.14159265358979+0i), TRUE, 2, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test @@ -198,8 +185,7 @@ public class TestBuiltin_format extends TestBase { @Test public void testformat37() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(213198964, 652424.52183908), .Names = c('null.deviance', 'deviance')), FALSE, 5L, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(structure(c(213198964, 652424.52183908), .Names = c('null.deviance', 'deviance')), FALSE, 5L, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test @@ -224,14 +210,12 @@ public class TestBuiltin_format extends TestBase { @Test public void testformat42() { - assertEval(Ignored.Unknown, - "argv <- list(c(2.5, 97.5), TRUE, 3, 0L, NULL, 3L, TRUE, FALSE, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(c(2.5, 97.5), TRUE, 3, 0L, NULL, 3L, TRUE, FALSE, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test public void testformat43() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(9.4, 10.2, 9.2, 4.4, 3.5, 2.7), .Dim = c(3L, 2L), .Dimnames = list(NULL, c('Estimate', 'Std.Err'))), FALSE, 2, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(structure(c(9.4, 10.2, 9.2, 4.4, 3.5, 2.7), .Dim = c(3L, 2L), .Dimnames = list(NULL, c('Estimate', 'Std.Err'))), FALSE, 2, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test @@ -246,8 +230,7 @@ public class TestBuiltin_format extends TestBase { @Test public void testformat47() { - assertEval(Ignored.Unknown, - "argv <- list(-0.01234+3.14159265358979i, FALSE, NULL, 14L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(-0.01234+3.14159265358979i, FALSE, NULL, 14L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test @@ -257,8 +240,7 @@ public class TestBuiltin_format extends TestBase { @Test public void testformat49() { - assertEval(Ignored.Unknown, - "argv <- list(3.141, FALSE, NULL, 13L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(3.141, FALSE, NULL, 13L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test @@ -293,7 +275,7 @@ public class TestBuiltin_format extends TestBase { @Test public void testformat56() { - assertEval(Ignored.Unknown, "argv <- structure(list(x = 0.04, digits = 3, nsmall = 3), .Names = c('x', 'digits', 'nsmall'));do.call('format', argv)"); + assertEval("argv <- structure(list(x = 0.04, digits = 3, nsmall = 3), .Names = c('x', 'digits', 'nsmall'));do.call('format', argv)"); } /** diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatC.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatC.java index 31f24a677604e9c5d1774cec92575cf41378cc79..b1f03422323a890898866bd9ffc934c2d517c674 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatC.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatC.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. */ @@ -47,7 +47,7 @@ public class TestBuiltin_formatC extends TestBase { @Test public void testformatC6() { - assertEval(Ignored.Unknown, "argv <- list(3L, 'integer', 3, 2L, 'd', '0', 10L); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))"); + assertEval("argv <- list(3L, 'integer', 3, 2L, 'd', '0', 10L); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))"); } @Test @@ -57,8 +57,7 @@ public class TestBuiltin_formatC extends TestBase { @Test public void testformatC8() { - assertEval(Ignored.Unknown, - "argv <- list(structure(48.4333681840033, .Names = 'value'), 'double', 5L, 4L, 'g', '', 12L); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))"); + assertEval("argv <- list(structure(48.4333681840033, .Names = 'value'), 'double', 5L, 4L, 'g', '', 12L); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))"); } @Test @@ -79,13 +78,12 @@ public class TestBuiltin_formatC extends TestBase { @Test public void testformatC12() { - assertEval(Ignored.Unknown, "argv <- list(5L, 'integer', 2, 2L, 'd', '', 10L); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))"); + assertEval("argv <- list(5L, 'integer', 2, 2L, 'd', '', 10L); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))"); } @Test public void testformatC13() { - assertEval(Ignored.Unknown, - "argv <- list(c(3.14159265358979e-05, 0.000314159265358979, 0.00314159265358979, 0.0314159265358979, 0.314159265358979, 3.14159265358979, 31.4159265358979, 314.159265358979, 3141.59265358979, 31415.9265358979), 'double', 5, 4, 'fg', '', c(15, 14, 13, 12, 11, 10, 9, 9, 9, 9)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))"); + assertEval("argv <- list(c(3.14159265358979e-05, 0.000314159265358979, 0.00314159265358979, 0.0314159265358979, 0.314159265358979, 3.14159265358979, 31.4159265358979, 314.159265358979, 3141.59265358979, 31415.9265358979), 'double', 5, 4, 'fg', '', c(15, 14, 13, 12, 11, 10, 9, 9, 9, 9)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatpval.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatpval.java index 305bd3eb08bc2bb7b7c643d75d68cb09d9795022..85b21c47804e23b12d56373699bc20d4d610971b 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatpval.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatpval.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. */ @@ -14,12 +14,10 @@ import org.junit.Test; import com.oracle.truffle.r.test.TestBase; -// Checkstyle: stop line length check - public class TestBuiltin_formatpval extends TestBase { @Test public void testformatpval1() { - assertEval(Ignored.Unknown, "argv <- structure(list(pv = 0.200965994008331, digits = 3), .Names = c('pv', 'digits'));do.call('format.pval', argv)"); + assertEval("argv <- structure(list(pv = 0.200965994008331, digits = 3), .Names = c('pv', 'digits'));do.call('format.pval', argv)"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gamma.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gamma.java index 4282428e7130162a35eae47912849fac69905474..f8d55fed542c996a76280563d055c25c01ef4a16 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gamma.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gamma.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. */ @@ -19,12 +19,12 @@ public class TestBuiltin_gamma extends TestBase { @Test public void testgamma1() { - assertEval(Ignored.Unknown, "argv <- list(c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1));gamma(argv[[1]]);"); + assertEval("argv <- list(c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1));gamma(argv[[1]]);"); } @Test public void testgamma2() { - assertEval(Ignored.Unknown, "argv <- list(FALSE);gamma(argv[[1]]);"); + assertEval("argv <- list(FALSE);gamma(argv[[1]]);"); } @Test @@ -34,12 +34,11 @@ public class TestBuiltin_gamma extends TestBase { @Test public void testgamma5() { - assertEval(Ignored.Unknown, "argv <- list(101);gamma(argv[[1]]);"); + assertEval("argv <- list(101);gamma(argv[[1]]);"); } @Test public void testgamma6() { - assertEval(Ignored.Unknown, - "argv <- list(c(-3.000001, -3, -3, -2.999999, -2.965, -2.93, -2.895, -2.86, -2.825, -2.79, -2.755, -2.72, -2.685, -2.65, -2.615, -2.58, -2.545, -2.51, -2.475, -2.44, -2.405, -2.37, -2.335, -2.3, -2.265, -2.23, -2.195, -2.16, -2.125, -2.09, -2.055, -2.02, -2.000001, -2, -1.999999, -1.985, -1.95, -1.915, -1.88, -1.845, -1.81, -1.775, -1.74, -1.705, -1.67, -1.635, -1.6, -1.565, -1.53, -1.495, -1.46, -1.425, -1.39, -1.355, -1.32, -1.285, -1.25, -1.215, -1.18, -1.145, -1.11, -1.075, -1.04, -1.005, -1.000001, -1, -0.999999, -0.97, -0.935, -0.9, -0.865, -0.83, -0.795, -0.76, -0.725, -0.69, -0.655, -0.62, -0.585, -0.55, -0.515, -0.48, -0.445, -0.41, -0.375, -0.34, -0.305, -0.27, -0.235, -0.2, -0.165, -0.13, -0.0949999999999998, -0.0599999999999996, -0.0249999999999999, -1e-06, 0, 1e-06, 0.0100000000000002, 0.0450000000000004, 0.0800000000000001, 0.115, 0.15, 0.185, 0.22, 0.255, 0.29, 0.325, 0.36, 0.395, 0.43, 0.465, 0.5, 0.535, 0.57, 0.605, 0.640000000000001, 0.675, 0.71, 0.745000000000001, 0.78, 0.815, 0.850000000000001, 0.885, 0.92, 0.955000000000001, 0.99, 1.025, 1.06, 1.095, 1.13, 1.165, 1.2, 1.235, 1.27, 1.305, 1.34, 1.375, 1.41, 1.445, 1.48, 1.515, 1.55, 1.585, 1.62, 1.655, 1.69, 1.725, 1.76, 1.795, 1.83, 1.865, 1.9, 1.935, 1.97, 2.005, 2.04, 2.075, 2.11, 2.145, 2.18, 2.215, 2.25, 2.285, 2.32, 2.355, 2.39, 2.425, 2.46, 2.495, 2.53, 2.565, 2.6, 2.635, 2.67, 2.705, 2.74, 2.775, 2.81, 2.845, 2.88, 2.915, 2.95, 2.985, 3.02, 3.055, 3.09, 3.125, 3.16, 3.195, 3.23, 3.265, 3.3, 3.335, 3.37, 3.405, 3.44, 3.475, 3.51, 3.545, 3.58, 3.615, 3.65, 3.685, 3.72, 3.755, 3.79, 3.825, 3.86, 3.895, 3.93, 3.965, 4));gamma(argv[[1]]);"); + assertEval("argv <- list(c(-3.000001, -3, -3, -2.999999, -2.965, -2.93, -2.895, -2.86, -2.825, -2.79, -2.755, -2.72, -2.685, -2.65, -2.615, -2.58, -2.545, -2.51, -2.475, -2.44, -2.405, -2.37, -2.335, -2.3, -2.265, -2.23, -2.195, -2.16, -2.125, -2.09, -2.055, -2.02, -2.000001, -2, -1.999999, -1.985, -1.95, -1.915, -1.88, -1.845, -1.81, -1.775, -1.74, -1.705, -1.67, -1.635, -1.6, -1.565, -1.53, -1.495, -1.46, -1.425, -1.39, -1.355, -1.32, -1.285, -1.25, -1.215, -1.18, -1.145, -1.11, -1.075, -1.04, -1.005, -1.000001, -1, -0.999999, -0.97, -0.935, -0.9, -0.865, -0.83, -0.795, -0.76, -0.725, -0.69, -0.655, -0.62, -0.585, -0.55, -0.515, -0.48, -0.445, -0.41, -0.375, -0.34, -0.305, -0.27, -0.235, -0.2, -0.165, -0.13, -0.0949999999999998, -0.0599999999999996, -0.0249999999999999, -1e-06, 0, 1e-06, 0.0100000000000002, 0.0450000000000004, 0.0800000000000001, 0.115, 0.15, 0.185, 0.22, 0.255, 0.29, 0.325, 0.36, 0.395, 0.43, 0.465, 0.5, 0.535, 0.57, 0.605, 0.640000000000001, 0.675, 0.71, 0.745000000000001, 0.78, 0.815, 0.850000000000001, 0.885, 0.92, 0.955000000000001, 0.99, 1.025, 1.06, 1.095, 1.13, 1.165, 1.2, 1.235, 1.27, 1.305, 1.34, 1.375, 1.41, 1.445, 1.48, 1.515, 1.55, 1.585, 1.62, 1.655, 1.69, 1.725, 1.76, 1.795, 1.83, 1.865, 1.9, 1.935, 1.97, 2.005, 2.04, 2.075, 2.11, 2.145, 2.18, 2.215, 2.25, 2.285, 2.32, 2.355, 2.39, 2.425, 2.46, 2.495, 2.53, 2.565, 2.6, 2.635, 2.67, 2.705, 2.74, 2.775, 2.81, 2.845, 2.88, 2.915, 2.95, 2.985, 3.02, 3.055, 3.09, 3.125, 3.16, 3.195, 3.23, 3.265, 3.3, 3.335, 3.37, 3.405, 3.44, 3.475, 3.51, 3.545, 3.58, 3.615, 3.65, 3.685, 3.72, 3.755, 3.79, 3.825, 3.86, 3.895, 3.93, 3.965, 4));gamma(argv[[1]]);"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grep.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grep.java index 29f31b22de0b47d61c6d3c54e56641d577185d63..83f201d7b1935d729c2a488790cfbd3be5464b24 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grep.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grep.java @@ -76,6 +76,12 @@ public class TestBuiltin_grep extends TestBase { assertEval("argv <- list('^[[:blank:]]*$', 'mtext(\\\'«Latin-1 accented chars»: éè øØ å<Å æ<Æ\\\', side = 3)', FALSE, FALSE, FALSE, FALSE, FALSE, FALSE); .Internal(grep(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]]))"); } + @Test + public void testgrep13() { + // grep('.__T__[[<-:', data, fixed = TRUE) + assertEval("argv <- list('.__T__[[<-:', '.__T__[[<-:base', FALSE, FALSE, FALSE, TRUE, FALSE, FALSE); .Internal(grep(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]]))"); + } + @Test public void testGrep() { assertEval("{ txt<-c(\"arm\",\"foot\",\"lefroo\", \"bafoobar\"); grep(\"foo\", txt) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java index 5c9ab0bd62f5986f7a3a3433eb5596f97f717833..6c0ecb1d2d5960deebdb19fb60f2c8c197de3bef 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java @@ -174,7 +174,7 @@ public class TestBuiltin_gsub extends TestBase { assertEval("{ gsub(\"a\",\"aa\", \"prAgue alley\") }"); assertEval("{ gsub(\"a\",\"aa\", \"prague alley\", fixed=TRUE) }"); assertEval("{ gsub(\"a\",\"aa\", \"prAgue alley\", fixed=TRUE) }"); - assertEval(Output.IgnoreWarningContext, "{ gsub(\"a\",\"aa\", \"prAgue alley\", fixed=TRUE, ignore.case=TRUE) }"); + assertEval("{ gsub(\"a\",\"aa\", \"prAgue alley\", fixed=TRUE, ignore.case=TRUE) }"); assertEval("{ gsub(\"([a-e])\",\"\\\\1\\\\1\", \"prague alley\") }"); assertEval("{ gsub(\"h\",\"\", c(\"hello\", \"hi\", \"bye\")) }"); assertEval("{ gsub(\"h\",\"\", c(\"hello\", \"hi\", \"bye\"), fixed=TRUE) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_inherits.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_inherits.java index 77fcee218b858d8dae875e1f758d5247b4cd87c4..6bbed855deb3945f9858829de9e3eb46294c2859 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_inherits.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_inherits.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -209,8 +209,8 @@ public class TestBuiltin_inherits extends TestBase { assertEval("{ inherits(getClass(\"ClassUnionRepresentation\"), \"classRepresentation\") }"); - assertEval(Output.IgnoreErrorContext, "{x <- 10;class(x) <- c(\"a\", \"b\");inherits(x, 2, c(TRUE)) ;}"); - assertEval(Output.IgnoreErrorContext, "{x <- 10;class(x) <- c(\"a\", \"b\");inherits(x, \"a\", 1) ;}"); + assertEval("{x <- 10;class(x) <- c(\"a\", \"b\");inherits(x, 2, c(TRUE)) ;}"); + assertEval("{x <- 10;class(x) <- c(\"a\", \"b\");inherits(x, \"a\", 1) ;}"); assertEval("inherits(NULL, 'NULL')"); } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_intToBits.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_intToBits.java index ceb2167bfc0ce15331bdba66838dca509d70021a..7f45267721fe11a59ad8f1bf4bcd9aa0071d93f8 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_intToBits.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_intToBits.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. */ @@ -38,18 +38,18 @@ public class TestBuiltin_intToBits extends TestBase { assertEval("intToBits(-1.56)"); assertEval("intToBits(-0.3)"); assertEval("intToBits('123')"); - assertEval(Output.IgnoreWarningContext, "intToBits(5+7i)"); + assertEval("intToBits(5+7i)"); assertEval("intToBits(NULL)"); assertEval("intToBits(c(1,2,3))"); assertEval("intToBits(c(5L,99L))"); assertEval("intToBits(integer(0))"); assertEval("intToBits(double(0))"); assertEval("intToBits(6:9)"); - assertEval(Output.IgnoreWarningContext, "intToBits('23rrff')"); + assertEval("intToBits('23rrff')"); assertEval("intToBits(new.env())"); assertEval("intToBits(environment)"); assertEval("intToBits(stdout())"); - assertEval(Output.IgnoreErrorContext, "intToBits(list(c(5,5,7,8),88,6L))"); + assertEval("intToBits(list(c(5,5,7,8),88,6L))"); assertEval("intToBits(list(5,5,7,8))"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfactor.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfactor.java index d4579d558c15801ee7fb236e42f73ddc014da42c..9b14bf8048ae86f693e6d53f25f8a533e94f2a66 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfactor.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfactor.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -30,6 +30,6 @@ public class TestBuiltin_isfactor extends TestBase { assertEval("{is.factor(1)}"); assertEval("{is.factor(c)}"); - assertEval(Output.IgnoreErrorContext, "{x<-1;class(x)<-\"factor\";is.factor(x)}"); + assertEval("{x<-1;class(x)<-\"factor\";is.factor(x)}"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfinite.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfinite.java index cb708368ec38737bdb3aabff832facfcae54a38a..0816c96c8e09e83d1cb86ac897fb05f147cd7887 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfinite.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfinite.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -29,7 +29,7 @@ public class TestBuiltin_isfinite extends TestBase { @Test public void testisfinite3() { - assertEval(Ignored.Unknown, "argv <- list(structure(485.051413351662, .Names = 'value'));is.finite(argv[[1]]);"); + assertEval("argv <- list(structure(485.051413351662, .Names = 'value'));is.finite(argv[[1]]);"); } @Test @@ -65,7 +65,7 @@ public class TestBuiltin_isfinite extends TestBase { @Test public void testisfinite10() { - assertEval(Ignored.Unknown, "argv <- list(structure(c(-32.6915744137254, -24.6945405669482, -24.6945405669482, -357.79068676373), .Dim = c(2L, 2L)));is.finite(argv[[1]]);"); + assertEval("argv <- list(structure(c(-32.6915744137254, -24.6945405669482, -24.6945405669482, -357.79068676373), .Dim = c(2L, 2L)));is.finite(argv[[1]]);"); } @Test @@ -80,8 +80,7 @@ public class TestBuiltin_isfinite extends TestBase { @Test public void testisfinite13() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(-0.560475646552213+0i, 0.7424437487+0.205661411508856i, 1.39139505579429-0.26763356813179i, 0.928710764113827-0.221714979045717i, -0.46926798541295+1.18846175213664i, 0.7424437487-0.205661411508856i, 0.460916205989202+0i, -0.452623703774585+0.170604003753717i, -0.094501186832143+0.54302538277632i, -0.331818442379127+0.612232958468282i, 1.39139505579429+0.26763356813179i, -0.452623703774585-0.170604003753717i, 0.400771450594052+0i, -0.927967220342259+0.479716843914174i, -0.790922791530657+0.043092176305418i, 0.928710764113827+0.221714979045717i, -0.094501186832143-0.54302538277632i, -0.927967220342259-0.479716843914174i, 0.701355901563686+0i, -0.600841318509537+0.213998439984336i, -0.46926798541295-1.18846175213664i, -0.331818442379127-0.612232958468282i, -0.790922791530657-0.043092176305418i, -0.600841318509537-0.213998439984336i, -0.625039267849257+0i), .Dim = c(5L, 5L)));is.finite(argv[[1]]);"); + assertEval("argv <- list(structure(c(-0.560475646552213+0i, 0.7424437487+0.205661411508856i, 1.39139505579429-0.26763356813179i, 0.928710764113827-0.221714979045717i, -0.46926798541295+1.18846175213664i, 0.7424437487-0.205661411508856i, 0.460916205989202+0i, -0.452623703774585+0.170604003753717i, -0.094501186832143+0.54302538277632i, -0.331818442379127+0.612232958468282i, 1.39139505579429+0.26763356813179i, -0.452623703774585-0.170604003753717i, 0.400771450594052+0i, -0.927967220342259+0.479716843914174i, -0.790922791530657+0.043092176305418i, 0.928710764113827+0.221714979045717i, -0.094501186832143-0.54302538277632i, -0.927967220342259-0.479716843914174i, 0.701355901563686+0i, -0.600841318509537+0.213998439984336i, -0.46926798541295-1.18846175213664i, -0.331818442379127-0.612232958468282i, -0.790922791530657-0.043092176305418i, -0.600841318509537-0.213998439984336i, -0.625039267849257+0i), .Dim = c(5L, 5L)));is.finite(argv[[1]]);"); } @Test @@ -96,7 +95,7 @@ public class TestBuiltin_isfinite extends TestBase { @Test public void testisfinite16() { - assertEval(Ignored.Unknown, "argv <- list(structure(numeric(0), .Dim = c(0L, 0L)));is.finite(argv[[1]]);"); + assertEval("argv <- list(structure(numeric(0), .Dim = c(0L, 0L)));is.finite(argv[[1]]);"); } @Test @@ -111,13 +110,12 @@ public class TestBuiltin_isfinite extends TestBase { @Test public void testisfinite19() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(100, -1e-13, Inf, -Inf, NaN, 3.14159265358979, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', ' NA')));is.finite(argv[[1]]);"); + assertEval("argv <- list(structure(c(100, -1e-13, Inf, -Inf, NaN, 3.14159265358979, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', ' NA')));is.finite(argv[[1]]);"); } @Test public void testisfinite20() { - assertEval(Ignored.Unknown, "argv <- list(structure(c(100L, 0L, NA, NA, NA, 3L, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', ' NA')));is.finite(argv[[1]]);"); + assertEval("argv <- list(structure(c(100L, 0L, NA, NA, NA, 3L, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', ' NA')));is.finite(argv[[1]]);"); } @Test @@ -127,7 +125,7 @@ public class TestBuiltin_isfinite extends TestBase { @Test public void testisfinite22() { - assertEval(Ignored.Unknown, "argv <- list(structure(1:7, .Dim = c(1L, 7L)));is.finite(argv[[1]]);"); + assertEval("argv <- list(structure(1:7, .Dim = c(1L, 7L)));is.finite(argv[[1]]);"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isinfinite.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isinfinite.java index 8697181ac8b8a104d668c470adde7284202ea058..59854d0c5001ea9d7d32041a5c5f66c810256dac 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isinfinite.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isinfinite.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. */ @@ -19,7 +19,7 @@ public class TestBuiltin_isinfinite extends TestBase { @Test public void testisinfinite1() { - assertEval(Ignored.Unknown, "argv <- list(structure(c(100L, 0L, NA, NA, NA, 3L, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', ' NA')));is.infinite(argv[[1]]);"); + assertEval("argv <- list(structure(c(100L, 0L, NA, NA, NA, 3L, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', ' NA')));is.infinite(argv[[1]]);"); } @Test @@ -29,13 +29,12 @@ public class TestBuiltin_isinfinite extends TestBase { @Test public void testisinfinite3() { - assertEval(Ignored.Unknown, "argv <- list(structure(logical(0), .Dim = c(0L, 0L)));is.infinite(argv[[1]]);"); + assertEval("argv <- list(structure(logical(0), .Dim = c(0L, 0L)));is.infinite(argv[[1]]);"); } @Test public void testisinfinite4() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(0.00241725013897913, 2.73568372449633e-07, 0.00400531454105884, 0.0305181933571734, 0.022064930648429, 0.000416097494498381, 0.0186357510997526, 0.00896237344987589, 0.00202331168264955, 0.00279067096737535, 0.0447487811957221, 0.000577210896095096, 0.00782925975125774, 0.033211430744327, 0.0093483442273581, 0.00136284952207105, 0.0275004422708864, 0.0135979349769553, 0.000181644594904405, 0.00803803085466393, 0.00350275333198457, 0.014998898960339, 5.39459255498146e-05, 0.00123860219686858, 1.13323906102913e-05, 0.0297916373848854, 0.0312890114433758, 5.85350754663798e-05, 0.0131002435454964, 0.00277072267615578, 0.0222123285012571, 0.00194205331979335, 0.0103231522531299, 0.0261098279661105, 0.0358853728812373, 1.13323906102913e-05, 0.0486308859679786, 0.000674881587747117, 0.0218633172580077, 0.000558592420498928, 0.000802158707806158, 0.0581913205761545, 0.000436809276845313, 0.00631994234432259, 0.000141965876420771, 0.000262833357340149, 0.0055965687842748, 0.000654737007593888, 0.0140931986366498, 0.00241538552182261, 0.00414822230660342, 0.00884150659070285, 0.0647626092888162, 0.0935599413167129, 0.00117891119201738, 0.00742609802768654, 0.0306399064130622, 0.0274290617824389, 0.00217883778937331, 0.0108387379377857, 0.0242348837396833, 0.0168720396936779, 0.022211269097018, 0.0355286679037712, 0.00017126708391638, 0.00443642409999561, 0.0068913158904869, 0.0635882367317516, 0.0566932963429416, 0.00904861729235097, 0.00038919481466495), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71')));is.infinite(argv[[1]]);"); + assertEval("argv <- list(structure(c(0.00241725013897913, 2.73568372449633e-07, 0.00400531454105884, 0.0305181933571734, 0.022064930648429, 0.000416097494498381, 0.0186357510997526, 0.00896237344987589, 0.00202331168264955, 0.00279067096737535, 0.0447487811957221, 0.000577210896095096, 0.00782925975125774, 0.033211430744327, 0.0093483442273581, 0.00136284952207105, 0.0275004422708864, 0.0135979349769553, 0.000181644594904405, 0.00803803085466393, 0.00350275333198457, 0.014998898960339, 5.39459255498146e-05, 0.00123860219686858, 1.13323906102913e-05, 0.0297916373848854, 0.0312890114433758, 5.85350754663798e-05, 0.0131002435454964, 0.00277072267615578, 0.0222123285012571, 0.00194205331979335, 0.0103231522531299, 0.0261098279661105, 0.0358853728812373, 1.13323906102913e-05, 0.0486308859679786, 0.000674881587747117, 0.0218633172580077, 0.000558592420498928, 0.000802158707806158, 0.0581913205761545, 0.000436809276845313, 0.00631994234432259, 0.000141965876420771, 0.000262833357340149, 0.0055965687842748, 0.000654737007593888, 0.0140931986366498, 0.00241538552182261, 0.00414822230660342, 0.00884150659070285, 0.0647626092888162, 0.0935599413167129, 0.00117891119201738, 0.00742609802768654, 0.0306399064130622, 0.0274290617824389, 0.00217883778937331, 0.0108387379377857, 0.0242348837396833, 0.0168720396936779, 0.022211269097018, 0.0355286679037712, 0.00017126708391638, 0.00443642409999561, 0.0068913158904869, 0.0635882367317516, 0.0566932963429416, 0.00904861729235097, 0.00038919481466495), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71')));is.infinite(argv[[1]]);"); } @Test @@ -46,8 +45,7 @@ public class TestBuiltin_isinfinite extends TestBase { @Test public void testisinfinite6() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(1.12411954394441, -0.567321126080105, 1.28594901629635, -0.519809468914999, -1.485548782458, -0.435305441405687, -0.281625943801696, -0.527525498975648, 2.60041695299567, NA), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10')));is.infinite(argv[[1]]);"); + assertEval("argv <- list(structure(c(1.12411954394441, -0.567321126080105, 1.28594901629635, -0.519809468914999, -1.485548782458, -0.435305441405687, -0.281625943801696, -0.527525498975648, 2.60041695299567, NA), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10')));is.infinite(argv[[1]]);"); } @Test @@ -57,26 +55,22 @@ public class TestBuiltin_isinfinite extends TestBase { @Test public void testisinfinite8() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(0.00544194018731062, 0.00542949133552226, 1.20718999105839e-05, 0.00505497198006266, 0.827687885653788, 0.00315385274195005, 0.0023164952286401, 0.00117183915211372, 2.09167441982205, 0.00193959227691399, 0.00358084102808485, 3.39138861812986e-05, 0.00163051710052444, 0.00168735925488057, 0.0167253073891896, 0.237074502262169, 0.0118967636015583, 0.00307437031103621, 0.00114371252369823, 0.000860763872820255, 0.00028432076263802, 0.00329557354736053, 0.000123683950933913, 0.00026114238659798, 0.00471892942651347, 0.00317288091968884, 6.76955217513137e-05, 0.0119061189538054, 0.00233356124758579, 0.00672098496026968, 0.134965372025281, 0.00102115420103838, 0.00114816901125044), .Names = c('Craig Dunain', 'Ben Rha', 'Ben Lomond', 'Goatfell', 'Bens of Jura', 'Cairnpapple', 'Scolty', 'Traprain', 'Lairig Ghru', 'Dollar', 'Lomonds', 'Cairn Table', 'Eildon Two', 'Cairngorm', 'Seven Hills', 'Knock Hill', 'Black Hill', 'Creag Beag', 'Kildcon Hill', 'Meall Ant-Suidhe', 'Half Ben Nevis', 'Cow Hill', 'N Berwick Law', 'Creag Dubh', 'Burnswark', 'Largo Law', 'Criffel', 'Acmony', 'Ben Nevis', 'Knockfarrel', 'Two Breweries', 'Cockleroi', 'Moffat Chase')));is.infinite(argv[[1]]);"); + assertEval("argv <- list(structure(c(0.00544194018731062, 0.00542949133552226, 1.20718999105839e-05, 0.00505497198006266, 0.827687885653788, 0.00315385274195005, 0.0023164952286401, 0.00117183915211372, 2.09167441982205, 0.00193959227691399, 0.00358084102808485, 3.39138861812986e-05, 0.00163051710052444, 0.00168735925488057, 0.0167253073891896, 0.237074502262169, 0.0118967636015583, 0.00307437031103621, 0.00114371252369823, 0.000860763872820255, 0.00028432076263802, 0.00329557354736053, 0.000123683950933913, 0.00026114238659798, 0.00471892942651347, 0.00317288091968884, 6.76955217513137e-05, 0.0119061189538054, 0.00233356124758579, 0.00672098496026968, 0.134965372025281, 0.00102115420103838, 0.00114816901125044), .Names = c('Craig Dunain', 'Ben Rha', 'Ben Lomond', 'Goatfell', 'Bens of Jura', 'Cairnpapple', 'Scolty', 'Traprain', 'Lairig Ghru', 'Dollar', 'Lomonds', 'Cairn Table', 'Eildon Two', 'Cairngorm', 'Seven Hills', 'Knock Hill', 'Black Hill', 'Creag Beag', 'Kildcon Hill', 'Meall Ant-Suidhe', 'Half Ben Nevis', 'Cow Hill', 'N Berwick Law', 'Creag Dubh', 'Burnswark', 'Largo Law', 'Criffel', 'Acmony', 'Ben Nevis', 'Knockfarrel', 'Two Breweries', 'Cockleroi', 'Moffat Chase')));is.infinite(argv[[1]]);"); } @Test public void testisinfinite9() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(0.648648743252693, 0.52170345712821, -0.338075767187078, 0.169770656775468, -1.86324282017776, 0.362268009067608, 0.136032794890515, 0.901814933704047, -0.671639624694386, 1.79387977353953, 0.714576709724596, -0.471811539980989, -0.857026690426369, 0.226899513968796, 0.568565310101759, -0.944564385994918, 0.693403222263985, 0.02231307737364, -0.276817414323803, -0.344452836733253, -0.844829717537689, -0.421779195680793, -0.154748062715674, 1.43960300137753, 0.256965508768852, -0.295370227475694, 0.507911869619344, -0.346156318366332, -0.187948961031579, -0.454073164294974, -0.0895014237058297, 1.91227371168715, 0.779246572061347, 0.606406152381391, -0.0628430973426908, 2.1063179091687, -1.32672093069913, -0.754254955100625, -0.59565543740158, -1.95946772292555, -0.495798772099865, -3.58086046245482, -0.721772682345538, -0.254468243441054, 2.41750264738881, -0.0647957309150968, 1.87354174039771, -0.552199273430865, 0.732944502427441, 0.703597322009966, 0.875011400025303, -0.916329805907907, -0.297942295133666, -0.239141969395332, -1.79620422664673, -1.34633804643361, -Inf, 1.84762640960041, -0.344523591926435, 1.12935189480329, -0.902874350916712, -0.187948961031579, 0.444184743731147, -0.595767030989317, -0.878351658910786, 0.131398128073247, -1.16349118303155, -0.612790192876235, -0.231519954928205, -0.944564385994918, 0.136032794890519, -0.250233723215235, -0.972829009134415, 0.576852333601859, 0.226899513968797, -0.316245505808486, 0.101419270213227, 2.16953626752671, -0.383691077846572, 0.547999893193889, 0.00183871707028874, -1.28758691932778, 0.0676445397107313, -0.809987759639438, -1.04896153736838, 0.156556073105978, 0.248659709506608, 1.27246860456928, 0.554771572109539, 1.2326801378144, 2.2926344791142, 1.00034303387372, -0.554771572109538), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93')));is.infinite(argv[[1]]);"); + assertEval("argv <- list(structure(c(0.648648743252693, 0.52170345712821, -0.338075767187078, 0.169770656775468, -1.86324282017776, 0.362268009067608, 0.136032794890515, 0.901814933704047, -0.671639624694386, 1.79387977353953, 0.714576709724596, -0.471811539980989, -0.857026690426369, 0.226899513968796, 0.568565310101759, -0.944564385994918, 0.693403222263985, 0.02231307737364, -0.276817414323803, -0.344452836733253, -0.844829717537689, -0.421779195680793, -0.154748062715674, 1.43960300137753, 0.256965508768852, -0.295370227475694, 0.507911869619344, -0.346156318366332, -0.187948961031579, -0.454073164294974, -0.0895014237058297, 1.91227371168715, 0.779246572061347, 0.606406152381391, -0.0628430973426908, 2.1063179091687, -1.32672093069913, -0.754254955100625, -0.59565543740158, -1.95946772292555, -0.495798772099865, -3.58086046245482, -0.721772682345538, -0.254468243441054, 2.41750264738881, -0.0647957309150968, 1.87354174039771, -0.552199273430865, 0.732944502427441, 0.703597322009966, 0.875011400025303, -0.916329805907907, -0.297942295133666, -0.239141969395332, -1.79620422664673, -1.34633804643361, -Inf, 1.84762640960041, -0.344523591926435, 1.12935189480329, -0.902874350916712, -0.187948961031579, 0.444184743731147, -0.595767030989317, -0.878351658910786, 0.131398128073247, -1.16349118303155, -0.612790192876235, -0.231519954928205, -0.944564385994918, 0.136032794890519, -0.250233723215235, -0.972829009134415, 0.576852333601859, 0.226899513968797, -0.316245505808486, 0.101419270213227, 2.16953626752671, -0.383691077846572, 0.547999893193889, 0.00183871707028874, -1.28758691932778, 0.0676445397107313, -0.809987759639438, -1.04896153736838, 0.156556073105978, 0.248659709506608, 1.27246860456928, 0.554771572109539, 1.2326801378144, 2.2926344791142, 1.00034303387372, -0.554771572109538), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93')));is.infinite(argv[[1]]);"); } @Test public void testisinfinite10() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(100, -1e-13, Inf, -Inf, NaN, 3.14159265358979, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', ' NA')));is.infinite(argv[[1]]);"); + assertEval("argv <- list(structure(c(100, -1e-13, Inf, -Inf, NaN, 3.14159265358979, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', ' NA')));is.infinite(argv[[1]]);"); } @Test public void testisinfinite11() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(0.140840156507829, 0.04056135019562, 0.0029302031336855, 0.244192917875952, 0.613916838192149, 0.0888451715064135, 0.0786481028238466, 0.000549230092684491, 0.00048785961836479, 0.235214398525727, 0.000402612842061681, 0.00423992719924668, 0.0355604120039037, 0.00432748168352161, 0.170388213068447, 0.466682597016338), .Names = c('1947', '1948', '1949', '1950', '1951', '1952', '1953', '1954', '1955', '1956', '1957', '1958', '1959', '1960', '1961', '1962')));is.infinite(argv[[1]]);"); + assertEval("argv <- list(structure(c(0.140840156507829, 0.04056135019562, 0.0029302031336855, 0.244192917875952, 0.613916838192149, 0.0888451715064135, 0.0786481028238466, 0.000549230092684491, 0.00048785961836479, 0.235214398525727, 0.000402612842061681, 0.00423992719924668, 0.0355604120039037, 0.00432748168352161, 0.170388213068447, 0.466682597016338), .Names = c('1947', '1948', '1949', '1950', '1951', '1952', '1953', '1954', '1955', '1956', '1957', '1958', '1959', '1960', '1961', '1962')));is.infinite(argv[[1]]);"); } @Test @@ -86,7 +80,7 @@ public class TestBuiltin_isinfinite extends TestBase { @Test public void testisinfinite13() { - assertEval(Ignored.Unknown, "argv <- list(structure(1:24, .Dim = 2:4));is.infinite(argv[[1]]);"); + assertEval("argv <- list(structure(1:24, .Dim = 2:4));is.infinite(argv[[1]]);"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java index 62ede3d12e1b0ba57a1ff17df6c7cf760218400d..0322c2fb15b31d0f72a46e157d86ae5b640881e2 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -149,7 +149,7 @@ public class TestBuiltin_isna extends TestBase { @Test public void testisna29() { - assertEval(Output.IgnoreWarningContext, "argv <- list(NULL);is.na(argv[[1]]);"); + assertEval("argv <- list(NULL);is.na(argv[[1]]);"); } @Test @@ -247,7 +247,7 @@ public class TestBuiltin_isna extends TestBase { assertEval("{ is.na(1[10]) }"); assertEval("{ is.na(c(1[10],2[10],3)) }"); assertEval("{ is.na(list(1[10],1L[10],list(),integer())) }"); - assertEval(Output.IgnoreWarningContext, "is.na(quote(x()))"); + assertEval("is.na(quote(x()))"); assertEval("is.na(is.na)"); assertEval("is.na(data.frame(col1=1:5, col2=c(NA, 1, NA, 2, NA)))"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isnan.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isnan.java index 3b125e3880841db988f13a4899a798d2437b4dd6..786da412a54b73c17033640145516ba780b74086 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isnan.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isnan.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. */ @@ -24,7 +24,7 @@ public class TestBuiltin_isnan extends TestBase { @Test public void testisnan2() { - assertEval(Ignored.Unknown, "argv <- list(structure(1:7, .Names = c('a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7')));is.nan(argv[[1]]);"); + assertEval("argv <- list(structure(1:7, .Names = c('a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7')));is.nan(argv[[1]]);"); } @Test @@ -34,7 +34,7 @@ public class TestBuiltin_isnan extends TestBase { @Test public void testisnan4() { - assertEval(Ignored.Unknown, "argv <- list(structure(NaN, .Dim = c(1L, 1L)));is.nan(argv[[1]]);"); + assertEval("argv <- list(structure(NaN, .Dim = c(1L, 1L)));is.nan(argv[[1]]);"); } @Test @@ -49,7 +49,7 @@ public class TestBuiltin_isnan extends TestBase { @Test public void testisnan7() { - assertEval(Ignored.Unknown, "argv <- list(structure(1:3, .Dim = c(3L, 1L)));is.nan(argv[[1]]);"); + assertEval("argv <- list(structure(1:3, .Dim = c(3L, 1L)));is.nan(argv[[1]]);"); } @Test @@ -59,6 +59,6 @@ public class TestBuiltin_isnan extends TestBase { @Test public void testisnan10() { - assertEval(Ignored.Unknown, "argv <- list(structure(c(1, 1, 1, 1, 1, 1), .Dim = 1:3));is.nan(argv[[1]]);"); + assertEval("argv <- list(structure(c(1, 1, 1, 1, 1, 1), .Dim = 1:3));is.nan(argv[[1]]);"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isunsorted.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isunsorted.java index be6652d29a371a85ce41558f533d0eaf7bf1cdb9..52fa1f06fbfdd44d2eb020184990b3c84df312bc 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isunsorted.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isunsorted.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -98,5 +98,6 @@ public class TestBuiltin_isunsorted extends TestBase { assertEval("{ is.unsorted(c(1,2,2,3), strictly=TRUE) }"); assertEval("{ is.unsorted(c(1+1i,2+1i,2+1i), strictly=FALSE) }"); assertEval("{ is.unsorted(c(1+1i,2+1i,2+1i), strictly=TRUE) }"); + assertEval(Output.IgnoreErrorContext, "{ is.unsorted(c(1,2,2), strictly=NA) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java index 4cfb24acda41b9dd827e6c07712462b071318f90..372f103da4a9ef759bf22ef55ce7720bc45dd42f 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -199,7 +199,8 @@ public class TestBuiltin_isvector extends TestBase { assertEval("{is.vector(c(TRUE,FALSE),\"logical\");}"); assertEval("{x<-1;class(x)<-\"a\";is.vector(x);}"); assertEval("{x<-1;names(x)<-\"a\";is.vector(x);}"); - assertEval("{is.vector(c(1,2), c(\"sss\", \"dddd\"));}"); - assertEval("{is.vector(c(1,2), TRUE);}"); + // FastR produces better error contexts + assertEval(Output.IgnoreErrorContext, "{is.vector(c(1,2), c(\"sss\", \"dddd\"));}"); + assertEval(Output.IgnoreErrorContext, "{is.vector(c(1,2), TRUE);}"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lapply.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lapply.java index 72228b0de6e2cac4b011399b7b08eb40007e2889..57999d315ee96783cf7b4493794ec37740b88664 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lapply.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lapply.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -33,6 +33,26 @@ public class TestBuiltin_lapply extends TestBase { assertEval("{ l <- list(list(1),list(2),list(3)); f <- function(a) { lapply(a, function(x) lapply(x, function(y) print(y))) }; f(l)}"); assertEval("{ .Internal(lapply(1:4, 42)) }"); + + assertEval("lapply(NULL, function(x){x})"); + assertEval("lapply(NA, FUN=function(x){x})"); + assertEval("lapply(FUN=function(x){x})"); + assertEval("lapply(1:4, NULL)"); + assertEval("lapply(1:4, NA)"); + assertEval(Output.IgnoreErrorContext, "lapply(X=1:4)"); + assertEval("lapply(X=function() {print('test')}, FUN=function(x){x})"); + assertEval(Output.IgnoreWhitespace, "lapply(X=c(function() {print(\"test1\")}, function() {print(\"test2\")}), FUN=function(x){x})"); + assertEval("lapply(X=environment(), FUN=function(x){x})"); + + assertEval("f <- function(...) { .Internal(lapply(NULL, function(x){x})) }; f()"); + assertEval("f <- function(...) { .Internal(lapply(NA, FUN=function(x){x})) }; f()"); + assertEval("f <- function(...) { .Internal(lapply(FUN=function(x){x})) }; f()"); + assertEval("f <- function(...) { .Internal(lapply(1:4, NULL)) }; f()"); + assertEval("f <- function(...) { .Internal(lapply(1:4, NA)) }; f()"); + assertEval("f <- function(...) { .Internal(lapply(X=1:4)) }; f()"); + assertEval(Output.IgnoreErrorContext, "f <- function(...) { .Internal(lapply(X=function() {print('test')}, FUN=function(x){x})) }; f()"); + assertEval(Ignored.ImplementationError, "f <- function(...) { .Internal(lapply(X=c(function() {print('test1')}, function() {print('test2')}), FUN=function(x){x})) }; f()"); + assertEval(Output.IgnoreErrorContext, "f <- function(...) { .Internal(lapply(X=environment(), FUN=function(x){x})) }; f()"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_levels.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_levels.java index 20125e3e04fa1e90698e325f7a7603bf653270f3..e327a1ad7c625c2ed306cabee97b622b0470502b 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_levels.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_levels.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -36,7 +36,7 @@ public class TestBuiltin_levels extends TestBase { assertEval("{ x <- 1 ; levels(x)<-c(\"cat\", \"dog\"); levels(x)}"); assertEval("{ x <- 1 ; levels(x)<-c(3, \"cat\"); levels(x);}"); assertEval("{ x <- 1 ; levels(x)<-c(1, \"cat\", 4.5, \"3\"); levels(x);}"); - assertEval(Output.IgnoreErrorContext, "{ x <- 1 ; levels(x)<-NULL; levels(notx)}"); + assertEval(Output.MayIgnoreErrorContext, "{ x <- 1 ; levels(x)<-NULL; levels(notx)}"); assertEval("{ x <- NULL; levels(x)<-\"dog\"; levels(x)}"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java index 30e927da8e3e374a2d622d882f1c950fce785be6..144683f6528eb0416e073f015e903d5cb76727fa 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -56,7 +56,7 @@ public class TestBuiltin_lgamma extends TestBase { @Test public void testlgamma9() { - assertEval(Output.IgnoreWarningContext, "argv <- list(Inf);do.call('lgamma', argv)"); + assertEval("argv <- list(Inf);do.call('lgamma', argv)"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_list.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_list.java index 28dbce4917542c18370338302cbfb1966da87a9e..0c1ddfeaa18ab25a7733b507ada92817b964df3f 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_list.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_list.java @@ -292,8 +292,7 @@ public class TestBuiltin_list extends TestBase { @Test public void testlist55() { - assertEval(Ignored.Unknown, - "argv <- list(object = c(0, 0, 0, 0, 0, 1.75368801162502e-134, 0, 0, 0, 2.60477585273833e-251, 1.16485035372295e-260, 0, 1.53160350210786e-322, 0.333331382328728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.44161262707711e-123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.968811545398e-173, 0, 8.2359965384697e-150, 0, 0, 0, 0, 6.51733217171341e-10, 0, 2.36840184577368e-67, 0, 9.4348408357524e-307, 0, 1.59959906013771e-89, 0, 8.73836857865034e-286, 7.09716190970992e-54, 0, 0, 0, 1.530425353017e-274, 8.57590058044551e-14, 0.333333106397154, 0, 0, 1.36895217898448e-199, 2.0226102635783e-177, 5.50445388209462e-42, 0, 0, 0, 0, 1.07846402051283e-44, 1.88605464411243e-186, 1.09156111051203e-26, 0, 3.0702877273237e-124, 0.333333209689785, 0, 0, 0, 0, 0, 0, 3.09816093866831e-94, 0, 0, 4.7522727332095e-272, 0, 0, 2.30093251441394e-06, 0, 0, 1.27082826644707e-274, 0, 0, 0, 0, 0, 0, 0, 4.5662025456054e-65, 0, 2.77995853978268e-149, 0, 0, 0));list(argv[[1]]);"); + assertEval("argv <- list(object = c(0, 0, 0, 0, 0, 1.75368801162502e-134, 0, 0, 0, 2.60477585273833e-251, 1.16485035372295e-260, 0, 1.53160350210786e-322, 0.333331382328728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.44161262707711e-123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.968811545398e-173, 0, 8.2359965384697e-150, 0, 0, 0, 0, 6.51733217171341e-10, 0, 2.36840184577368e-67, 0, 9.4348408357524e-307, 0, 1.59959906013771e-89, 0, 8.73836857865034e-286, 7.09716190970992e-54, 0, 0, 0, 1.530425353017e-274, 8.57590058044551e-14, 0.333333106397154, 0, 0, 1.36895217898448e-199, 2.0226102635783e-177, 5.50445388209462e-42, 0, 0, 0, 0, 1.07846402051283e-44, 1.88605464411243e-186, 1.09156111051203e-26, 0, 3.0702877273237e-124, 0.333333209689785, 0, 0, 0, 0, 0, 0, 3.09816093866831e-94, 0, 0, 4.7522727332095e-272, 0, 0, 2.30093251441394e-06, 0, 0, 1.27082826644707e-274, 0, 0, 0, 0, 0, 0, 0, 4.5662025456054e-65, 0, 2.77995853978268e-149, 0, 0, 0));list(argv[[1]]);"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lm.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lm.java index 026eee8044e008acebd75ae9d53b8734eef55f16..1761b0e1166ffd9fb0fc823ec25a9a9daba7c57b 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lm.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lm.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. */ @@ -36,22 +36,22 @@ public class TestBuiltin_lm extends TestBase { @Test public void testlm334() { - assertEval(Ignored.Unknown, "require(stats);" + "lm(data = LifeCycleSavings, formula = sr ~ pop15 + pop75 + dpi + ddpi)"); + assertEval("require(stats);" + "lm(data = LifeCycleSavings, formula = sr ~ pop15 + pop75 + dpi + ddpi)"); } @Test public void testlm445() { - assertEval(Ignored.Unknown, "require(stats);" + "lm(data = attitude, formula = rating ~ .)"); + assertEval("require(stats);" + "lm(data = attitude, formula = rating ~ .)"); } @Test public void testlm875() { - assertEval(Ignored.Unknown, "require(stats); lm(data = mtcars, formula = 100/mpg ~ disp + hp + wt + am)"); + assertEval("require(stats); lm(data = mtcars, formula = 100/mpg ~ disp + hp + wt + am)"); } @Test public void testlm876() { - assertEval(Ignored.Unknown, "require(stats); lm(data = npk, formula = yield ~ block + N * P * K, singular.ok = TRUE)"); + assertEval("require(stats); lm(data = npk, formula = yield ~ block + N * P * K, singular.ok = TRUE)"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lockEnvironment.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lockEnvironment.java index 725d9b47df88cb9f3c774ae1ffa574e8ca2a0934..46fe71dbd587b3338f7ab0e03d598e60674468ef 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lockEnvironment.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lockEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -35,7 +35,7 @@ public class TestBuiltin_lockEnvironment extends TestBase { assertEval("e <- new.env(); e$a <- 'foo'; lockEnvironment(e, FALSE); e$b <- 123"); assertEval("e <- new.env(); e$a <- 'foo'; lockEnvironment(e, FALSE); e$a <- 123"); assertEval("e <- new.env(); e$a <- 'foo'; lockEnvironment(e, 'a'); e$b <- 123"); - assertEval(Ignored.MissingBuiltin, "e <- new.env(); e$a <- 'foo'; lockEnvironment(e, 'a'); e$a <- 123"); + assertEval("e <- new.env(); e$a <- 'foo'; lockEnvironment(e, 'a'); e$a <- 123"); assertEval("e <- new.env(); e$a <- 'foo'; lockEnvironment(e, logical()); e$b <- 123"); assertEval(Ignored.MissingBuiltin, "e <- new.env(); e$a <- 'foo'; lockEnvironment(e, logical()); e$a <- 123"); } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log.java index 1cb8f1375ebfd0fb2fa850c12c7d84df6fe0584c..4e5da9071abda26fdb9bc07abc9dd67b653c1032 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -34,4 +34,140 @@ public class TestBuiltin_log extends TestBase { assertEval("{ log(c(2,3), NA) } "); assertEval("{ log(c(2,3), 0/0) } "); } + + @Test + public void testLogLogical() { + assertEval("{ log(T) }"); + assertEval("{ log(c(T)) }"); + assertEval("{ log(c(T, F)) }"); + assertEval("{ log(c(T, F), T) }"); + assertEval("{ log(T, T) }"); + assertEval("{ log(T, F) }"); + assertEval("{ log(F, F) }"); + assertEval("{ log(F, T) }"); + assertEval("{ log(c(T, T), NA) }"); + assertEval("{ log(c(T, T), NaN) }"); + } + + @Test + public void testLogInt() { + assertEval("{ log(1L) }"); + assertEval("{ log(-1L) }"); + assertEval("{ log(0L) }"); + assertEval("{ log(NA_integer_) }"); + assertEval("{ log(0L, NA_integer_) }"); + assertEval("{ log(c(0L, NA_integer_)) }"); + assertEval("{ log(1L, 1L) }"); + assertEval("{ log(10L, 1L) }"); + assertEval("{ log(10L, -1L) }"); + assertEval("{ log(10L, 10L) }"); + assertEval("{ log(c(1L, 1L, 0L, 10L), 10L) }"); + assertEval("{ log(c(1L, 0L, 10L), 1L) }"); + assertEval("{ log(c(1L, 2L), NA) }"); + assertEval("{ log(c(1L, 2L), NaN) }"); + assertEval("{ log(c(1L, 2L, NA)) }"); + } + + @Test + public void testLogDouble() { + assertEval("{ log(1.1) }"); + assertEval("{ log(-1.1) }"); + assertEval("{ log(0.0) }"); + assertEval("{ log(NA_real_) }"); + assertEval("{ log(10, NA_real_) }"); + assertEval("{ log(c(10, NA_real_)) }"); + assertEval("{ log(1.0, 1.0) }"); + assertEval("{ log(10.0, 1.0) }"); + assertEval("{ log(10.0, -1.0) }"); + assertEval("{ log(10.0, 10.0) }"); + assertEval("{ log(c(1.0, 0.0, 10.0), 10.0) }"); + assertEval("{ log(c(1.0, 0.0, 10.0), 1.0) }"); + assertEval("{ log(c(1.0, 2.0), NA) }"); + assertEval("{ log(c(1.0, 2.0), NaN) }"); + assertEval("{ log(c(1.0, 2.0, NA)) }"); + } + + @Test + public void testLogComplex() { + assertEval("{ log(0+0i) }"); + + // NaN warnigns + assertEval("{ log(0+0i, 0) }"); + assertEval("{ log(0L, 0+0i) }"); + assertEval("{ log(0.0, 0+0i) }"); + assertEval("{ log(F, 0+0i) }"); + assertEval("{ log(0+0i, 0+0i) }"); + + // division by complex(r=0, i=0) returns NaN+NaNi, instead of -Inf+NaNi + assertEval(Ignored.ImplementationError, "{ log(0+0i, 1) }"); + + assertEval("{ log(1+1i) }"); + assertEval("{ log(complex(real=NA, imaginary=1i)) }"); + assertEval("{ log(complex(real=1, imaginary=NA)) }"); + assertEval("{ log(complex(real=NA, imaginary=NA)) }"); + assertEval("{ log(NA_complex_) }"); + assertEval("{ log(1+1i, NA_complex_) }"); + assertEval("{ log(c(1+1i, NA_complex_)) }"); + assertEval("{ log(1+1i, 0) }"); + + // division by complex(r=0, i=0) returns NaN+NaNi, instead of -Inf+NaNi + assertEval(Ignored.ImplementationError, "{ log(1+1i, 1) }"); + + assertEval("{ log(10+1i, 10) }"); + assertEval("{ log(10-1i, 10) }"); + assertEval("{ log(-10-1i, 10) }"); + assertEval("{ log(10+1i, -10) }"); + assertEval("{ log(10+10i, 10) }"); + assertEval("{ log(c(1+1i)) }"); + assertEval("{ log(c(1+1i), 0) }"); + + assertEval("{ log(c(1+1i, 2+2i), NA) }"); + assertEval("{ log(c(1+1i, 2+2i), NaN) }"); + assertEval("{ log(c(1+1i, 2+2i), complex(real=1, imaginary=NaN)) }"); + assertEval("{ log(c(1+1i, 2+2i), complex(real=NaN, imaginary=1)) }"); + assertEval("{ log(c(1+1i, 2+2i), complex(real=NaN, imaginary=NaN)) }"); + assertEval("{ log(c(1+1i, 2+2i), complex(real=1, imaginary=NA)) }"); + assertEval("{ log(c(1+1i, 2+2i), complex(real=NA, imaginary=1)) }"); + assertEval("{ log(c(1+1i, 2+2i, complex(real=NA, imaginary=NA))) }"); + + assertEval("{ log(c(10+1i, 10), 10) }"); + assertEval("{ log(c(10+10i, 10), 10) }"); + assertEval("{ log(c(1+1i, 2+1i)) }"); + + assertEval("{ log(c(10, 10+10i), 10) }"); + assertEval("{ log(c(10.0, 10+10i), 10) }"); + assertEval("{ log(c(T, 10+10i), 10) }"); + + assertEval("{ log(1, 1+1i) }"); + assertEval("{ log(10, 10+10i) }"); + assertEval("{ log(1.0, 1+1i) }"); + assertEval("{ log(10.0, 1+1i) }"); + assertEval("{ log(T, 1+1i) }"); + + assertEval("{ log(1+1i, 1+1i) }"); + assertEval("{ log(1+1i, 1-1i) }"); + assertEval("{ log(1+1i, -1-1i) }"); + assertEval("{ log(10+10i, 10+10i) }"); + assertEval("{ log(1+1i, 10+10i) }"); + + assertEval("{ log(c(10, 10), 10+10i) }"); + assertEval("{ log(c(10.0, 10.0), 10+10i) }"); + assertEval("{ log(c(T, F), 1+1i) }"); + assertEval("{ log(c(10+10i, 10+10i), 10+10i) }"); + // division by complex(r=0, i=0) returns NaN+NaNi, instead of -Inf+NaNi + assertEval(Ignored.ImplementationError, "{ log(complex(real=sqrt(.5), imaginary=sqrt(.5)), 1) }"); + } + + @Test + public void testProducedManyNaNsButOneWarnig() { + assertEval("{ log(c(F, F), F) }"); + assertEval("{ log(c(1L, 1L), 1L) }"); + assertEval("{ log(c(1.0, 1.0), 1.0) }"); + assertEval("{ log(c(0+0i, 0+0i), 0) }"); + + assertEval("{ log(c(F, F), 0+0i) }"); + assertEval("{ log(c(0L, 0L), 0+0i) }"); + assertEval("{ log(c(0.0, 0.0), 0+0i) }"); + assertEval("{ log(c(0+0i, 0+0i), 0+0i) }"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java index 9988eac042eb0b431b23b0e8d09dd63d67b35ebc..9d88cf794bd26b6ff7cefb48deaa23a2c76a609e 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -184,13 +184,13 @@ public class TestBuiltin_max extends TestBase { assertEval("{ max(\"42\", \"7\") }"); assertEval("{ max(as.double(NA), na.rm=FALSE) }"); - assertEval(Output.IgnoreWarningContext, "{ max(as.double(NA), as.double(NA), na.rm=TRUE) }"); + assertEval("{ max(as.double(NA), as.double(NA), na.rm=TRUE) }"); assertEval("{ max(as.double(NA), as.double(NA), na.rm=FALSE) }"); assertEval("{ max(as.integer(NA), na.rm=FALSE) }"); assertEval("{ max(as.integer(NA), as.integer(NA), na.rm=FALSE) }"); - assertEval(Output.IgnoreWarningContext, "{ max(as.character(NA), na.rm=TRUE) }"); + assertEval("{ max(as.character(NA), na.rm=TRUE) }"); assertEval("{ max(as.character(NA), na.rm=FALSE) }"); - assertEval(Output.IgnoreWarningContext, "{ max(as.character(NA), as.character(NA), na.rm=TRUE) }"); + assertEval("{ max(as.character(NA), as.character(NA), na.rm=TRUE) }"); assertEval("{ max(as.character(NA), as.character(NA), na.rm=FALSE) }"); assertEval("{ max(42L, as.integer(NA), na.rm=TRUE) }"); assertEval("{ max(42L, as.integer(NA), na.rm=FALSE) }"); @@ -216,8 +216,10 @@ public class TestBuiltin_max extends TestBase { assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ max(integer(0)) }"); assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ max(integer()) }"); - assertEval(Output.IgnoreWarningContext, "{ max(as.double(NA), na.rm=TRUE) }"); + assertEval("{ max(as.double(NA), na.rm=TRUE) }"); assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ max(as.integer(NA), na.rm=TRUE) }"); assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ max(as.integer(NA), as.integer(NA), na.rm=TRUE) }"); + + assertEval("max(c(1,NA,2), na.rm=NA)"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mean.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mean.java index a0837400703f51f15480247f9ccef54fc5b2f9e5..fa3485703328d226c661561007ec7254f68f3503 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mean.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mean.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -119,7 +119,7 @@ public class TestBuiltin_mean extends TestBase { @Test public void testmean22() { - assertEval(Output.IgnoreWarningContext, "argv <- structure(list(x = structure(c(2L, 1L, 2L, 2L), .Label = c('FALSE', 'TRUE'), class = 'factor')), .Names = 'x');do.call('mean', argv)"); + assertEval("argv <- structure(list(x = structure(c(2L, 1L, 2L, 2L), .Label = c('FALSE', 'TRUE'), class = 'factor')), .Names = 'x');do.call('mean', argv)"); } @Test 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 7f3b4879819d469b83e1d87aa9bce42d5c4f4345..e27d7728fc5c1f0ad654ae6a0d25cf668c7bb9a3 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 @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -20,6 +20,7 @@ public class TestBuiltin_mget extends TestBase { @Test public void testMGet() { assertEval("{ a<- 1; b <- 2; mget(c(\"a\", \"b\")) }"); + assertEval("{ a<- 1; b <- 2; mget(c('a', 'b'), envir=1) }"); assertEval("{ a<- 1; b <- 2; f <- function() { mget(c(\"a\", \"b\"), inherits=TRUE)}; f() }"); assertEval("{ a<- 1; mget(c(\"a\", \"b\"), ifnotfound=list(100)) }"); assertEval("{ b <- 2; f <- function() { mget(c(\"a\", \"b\"), ifnotfound=list(100), inherits=TRUE)}; f() }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java index 8cf0b4359dd248d93f856ad87479d6cdd89a5f2c..c8c5ab5a200d2b5772ecd340b6527f238a8f9a47 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -152,13 +152,13 @@ public class TestBuiltin_min extends TestBase { assertEval("{ min(\"42\", \"7\") }"); assertEval("{ min(as.double(NA), na.rm=FALSE) }"); - assertEval(Output.IgnoreWarningContext, "{ min(as.double(NA), as.double(NA), na.rm=TRUE) }"); + assertEval("{ min(as.double(NA), as.double(NA), na.rm=TRUE) }"); assertEval("{ min(as.double(NA), as.double(NA), na.rm=FALSE) }"); assertEval("{ min(as.integer(NA), na.rm=FALSE) }"); assertEval("{ min(as.integer(NA), as.integer(NA), na.rm=FALSE) }"); - assertEval(Output.IgnoreWarningContext, "{ min(as.character(NA), na.rm=TRUE) }"); + assertEval("{ min(as.character(NA), na.rm=TRUE) }"); assertEval("{ min(as.character(NA), na.rm=FALSE) }"); - assertEval(Output.IgnoreWarningContext, "{ min(as.character(NA), as.character(NA), na.rm=TRUE) }"); + assertEval("{ min(as.character(NA), as.character(NA), na.rm=TRUE) }"); assertEval("{ min(as.character(NA), as.character(NA), na.rm=FALSE) }"); assertEval("{ min(42L, as.integer(NA), na.rm=TRUE) }"); assertEval("{ min(42L, as.integer(NA), na.rm=FALSE) }"); @@ -175,8 +175,10 @@ public class TestBuiltin_min extends TestBase { assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ min(integer(0)) }"); assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ min(integer()) }"); - assertEval(Output.IgnoreWarningContext, "{ min(as.double(NA), na.rm=TRUE) }"); + assertEval("{ min(as.double(NA), na.rm=TRUE) }"); assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ min(as.integer(NA), na.rm=TRUE) }"); assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ min(as.integer(NA), as.integer(NA), na.rm=TRUE) }"); + + assertEval("min(c(1,NA,2), na.rm=NA)"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_missing.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_missing.java index 2de37d13ee3167be2e956cca6cbae8f29cb74ed9..b7558998d141221ba39df636212ae6755a262f5a 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_missing.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_missing.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -47,5 +47,7 @@ public class TestBuiltin_missing extends TestBase { assertEval("{ f <- function(x) { print(missing(x)); g(x) }; g <- function(y=3) { print(missing(y)); k(y) }; k <- function(l=4) { print(missing(l)); l }; f() }"); assertEval("{ f <- function(x) { print(missing(x)) ; g(x) } ; g <- function(y=1) { print(missing(y)) ; h(y) } ; h <- function(z) { print(missing(z)) ; z } ; f() }"); assertEval("{ f <- function(a,b,c,d,e,env) (length(objects(env, all.names = TRUE, pattern = \"^[.]__[CTA]_\"))); f2 <- function(env) (length(objects(env, all.names = TRUE, pattern = \"^[.]__[CTA]_\"))); f(); f2() }"); + + assertEval("{ f <- function(a) { missing(\"a\") }; f(); f(1) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java index cd568a219dfdb357ab3e656147f43c3f6ef9d095..2088466650701001c613ccbddd3d88bcef027c74 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java index a55986b74187308bfc40b5ade993b58e108b5314..704e3e765b9131302030c968266e2eee21995be7 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -74,7 +74,7 @@ public class TestBuiltin_nchar extends TestBase { @Test public void testnchar13() { - assertEval("argv <- list(structure(c('rpart', 'recommended', '4.1-1', '2013-03-20', 'c(person(\\\'Terry\\\', \\\'Therneau\\\', role = \\\'aut\\\',\\n\\t email = \\\'therneau@mayo.edu\\\'),\\n person(\\\'Beth\\\', \\\'Atkinson\\\', role = \\\'aut\\\',\\t\\n\\t email = \\\'atkinson@mayo.edu\\\'),\\n person(\\\'Brian\\\', \\\'Ripley\\\', role = c(\\\'aut\\\', \\\'trl\\\', \\\'cre\\\'),\\n email = \\\'ripley@stats.ox.ac.uk\\\',\\n\\t\\t comment = \\\'author of R port\\\'))', 'Recursive partitioning and regression trees', 'Recursive Partitioning', 'R (>= 2.14.0), graphics, stats, grDevices', 'survival', 'GPL-2 | GPL-3', 'yes', 'yes', 'Maintainers are not available to give advice on using a package\\nthey did not author.', '2013-03-20 07:27:05 UTC; ripley', 'Terry Therneau [aut],\\n Beth Atkinson [aut],\\n Brian Ripley [aut, trl, cre] (author of R port)', 'Brian Ripley <ripley@stats.ox.ac.uk>'), .Names = c('Package', 'Priority', 'Version', 'Date', 'Authors@R', 'Description', 'Title', 'Depends', 'Suggests', 'License', 'LazyData', 'ByteCompile', 'Note', 'Packaged', 'Author', 'Maintainer')), 'c', TRUE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))"); + assertEval("argv <- list(structure(c('rpart', 'recommended', '4.1-1', '2013-03-20', 'c(person(\\\'Terry\\\', \\\'Therneau\\\', role = \\\'aut\\\',\\n\\t email = \\\'therneau@mayo.edu\\\'),\\n person(\\\'Beth\\\', \\\'Atkinson\\\', role = \\\'aut\\\',\\t\\n\\t email = \\\'atkinson@mayo.edu\\\'),\\n person(\\\'Brian\\\', \\\'Ripley\\\', role = c(\\\'aut\\\', \\\'trl\\\', \\\'cre\\\'),\\n email = \\\'ripley@stats.ox.ac.uk\\\',\\n\\t\\t comment = \\\'author of R port\\\'))', 'Recursive partitioning and regression trees', 'Recursive Partitioning', 'R (>= 2.14.0), graphics, stats, grDevices', 'survival', 'GPL-2 | GPL-3', 'yes', 'yes', 'Maintainers are not available to give advice on using a package\\nthey did not author.', '2013-03-20 07:27:05 UTC; ripley', 'Terry Therneau [aut],\\n Beth Atkinson [aut],\\n Brian Ripley [aut, trl, cre] (author of R port)', 'Brian Ripley <ripley@stats.ox.ac.uk>'), .Names = c('Package', 'Priority', 'Version', 'Date', 'Authors@R', 'Description', 'Title', 'Depends', 'Suggests', 'License', 'LazyData', 'ByteCompile', 'Note', 'Packaged', 'Author', 'Maintainer')), 'c', TRUE, FALSE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))"); } @Test @@ -84,7 +84,29 @@ public class TestBuiltin_nchar extends TestBase { assertEval("{ nchar(c(10,130)) }"); assertEval("{ .Internal(nchar(c(10,130), 'chars', FALSE, FALSE)) }"); assertEval("{ .Internal(nchar('ff', 'chars', FALSE, FALSE)) }"); - assertEval("v <- c(a=1,b=1234,c='ff',d='gg'); dim(v) <- c(foo=2,bar=2); dimnames(v) <- list(a=c('foo', 'bar'), n=c('f','g')); nchar(v)"); } + + @Test + public void testNCharKeepNA() { + assertEval("nchar(c('aasd', NA), keepNA=NA)"); + assertEval("nchar(c('aasd', NA, 'asdasd'), keepNA=TRUE)"); + } + + @Test + public void testNCharTypeMatching() { + assertEval("nchar('aasd', type='cha')"); + assertEval("nchar('aasd', type='charsxzy')"); + assertEval("nchar('aasd', type='')"); + } + + @Test + public void testNULLAndMissing() { + assertEval("nchar()"); + assertEval("nchar(type = 'chars', allowNA = FALSE, keepNA = NA)"); + assertEval("nchar(x=NULL)"); + assertEval("nchar(x=NULL, type = 'chars', allowNA = FALSE, keepNA = NA)"); + assertEval("nchar(wrongArg=\"a\")"); + assertEval("nchar(wrongArg='a')"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ngettext.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ngettext.java index cc92051e78a72a13df17cc362d5dc650d617a0de..640757eabc316772033a7e6266165484d17150fe 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ngettext.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ngettext.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -36,14 +36,14 @@ public class TestBuiltin_ngettext extends TestBase { assertEval("{ ngettext(1, \"a\", c(\"b\")) }"); assertEval("{ ngettext(c(1), \"a\", \"b\") }"); assertEval("{ ngettext(c(1,2), \"a\", \"b\") }"); - assertEval(Output.IgnoreWarningContext, "{ ngettext(1+1i, \"a\", \"b\") }"); - assertEval(Output.IgnoreErrorContext, "{ ngettext(1, NULL, \"b\") }"); - assertEval(Output.IgnoreErrorContext, "{ ngettext(1, \"a\", NULL) }"); - assertEval(Output.IgnoreErrorContext, "{ ngettext(1, NULL, NULL) }"); - assertEval(Output.IgnoreErrorContext, "{ ngettext(1, c(\"a\", \"c\"), \"b\") }"); - assertEval(Output.IgnoreErrorContext, "{ ngettext(1, \"a\", c(\"b\", \"c\")) }"); - assertEval(Output.IgnoreErrorContext, "{ ngettext(1, c(1), \"b\") }"); - assertEval(Output.IgnoreErrorContext, "{ ngettext(1, \"a\", c(1)) }"); - assertEval(Output.IgnoreErrorContext, "{ ngettext(-1, \"a\", \"b\") }"); + assertEval("{ ngettext(1+1i, \"a\", \"b\") }"); + assertEval("{ ngettext(1, NULL, \"b\") }"); + assertEval("{ ngettext(1, \"a\", NULL) }"); + assertEval("{ ngettext(1, NULL, NULL) }"); + assertEval("{ ngettext(1, c(\"a\", \"c\"), \"b\") }"); + assertEval("{ ngettext(1, \"a\", c(\"b\", \"c\")) }"); + assertEval("{ ngettext(1, c(1), \"b\") }"); + assertEval("{ ngettext(1, \"a\", c(1)) }"); + assertEval("{ ngettext(-1, \"a\", \"b\") }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.java index c43232942555d24f347259f323d689e0fd7ed778..0c86bc1ebd0f764739295431dfea30a417752a33 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.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. */ @@ -76,11 +76,17 @@ public class TestBuiltin_nzchar extends TestBase { public void keepNATests() { assertEval("nzchar(c('asdasd', NA), keepNA=TRUE)"); assertEval("nzchar(c('asdasd', NA), keepNA=FALSE)"); + assertEval("nzchar(c('aasd', NA), keepNA=NA)"); } @Test public void nonStringArgs() { assertEval("nzchar(list('x', 42, list('a'), list()))"); assertEval("nzchar(NULL)"); + assertEval("nzchar(NA)"); + assertEval("nzchar(keepNA=F)"); + assertEval("nzchar(keepNA=NA)"); + assertEval("nchar(wrongArgName=\"a\")"); + assertEval("nchar(wrongArgName='a')"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_on_exit.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_on_exit.java index 569fe28f7c79e5e8c8a4bf37458544ada0e5c7cb..d9cf000cb81c5bd0f0cfabe42736c4a263f74d60 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_on_exit.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_on_exit.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -19,13 +19,14 @@ public class TestBuiltin_on_exit extends TestBase { @Test public void testOnExit() { - assertEval("n = function() { on.exit(print(\"test\")); print(\"some\") }; n()"); - assertEval("n = function() { on.exit(print(\"test\", TRUE)); print(\"some\") }; n()"); - assertEval("n = function() { on.exit(print(\"test\")); on.exit(); print(\"some\") }; n()"); - assertEval("n = function() { on.exit(print(\"test\")); on.exit(print(\"test2\", TRUE)); print(\"some\") }; n()"); - assertEval("n = function() { on.exit(print(\"test\")); on.exit(print(\"test2\")); print(\"some\") }; n()"); - assertEval("n = function() { on.exit(print(\"test\", TRUE)); on.exit(print(\"test2\")); print(\"some\") }; n()"); - assertEval("n = function() { on.exit(print(\"test\")); on.exit(print(\"test2\")); print(\"some\"); on.exit() }; n()"); - assertEval("n = function() { on.exit() }; n()"); + assertEval("f <- function() { on.exit(print('test')); print('some') }; f()"); + assertEval("f <- function() { on.exit(print('test', TRUE)); print('some') }; f()"); + assertEval("f <- function() { on.exit(print('test')); on.exit(); print('some') }; f()"); + assertEval("f <- function() { on.exit(print('test')); on.exit(print('test2', TRUE)); print('some') }; f()"); + assertEval("f <- function() { on.exit(print('test')); on.exit(print('test2')); print('some') }; f()"); + assertEval("f <- function() { on.exit(print('test', TRUE)); on.exit(print('test2')); print('some') }; f()"); + assertEval("f <- function() { on.exit(print('test')); on.exit(print('test2')); print('some'); on.exit() }; f()"); + assertEval("f <- function() { on.exit() }; f()"); + assertEval("f <- function() { on.exit(return(5)); return(1) }; f()"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java index 1d26cefe1010e25bc9e349863b35c87544bead8b..7765b87195d4c999bc99dd80a8f038163416a862 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java @@ -181,7 +181,7 @@ public class TestBuiltin_operators extends TestBase { @Test public void testoperators33() { - assertEval(Output.IgnoreWarningContext, "argv <- list(c(20.8, 11.2, 6.2, 12.8, 43.4), c(10.4, 5.6, 3.1, 6.4, 21.7, 0, 10.4, 5.6, 3.1, 6.4, 21.7));`+`(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(c(20.8, 11.2, 6.2, 12.8, 43.4), c(10.4, 5.6, 3.1, 6.4, 21.7, 0, 10.4, 5.6, 3.1, 6.4, 21.7));`+`(argv[[1]],argv[[2]]);"); } @Test @@ -1048,8 +1048,7 @@ public class TestBuiltin_operators extends TestBase { @Test public void testoperators207() { - assertEval(Ignored.Unknown, - "argv <- list(structure(list(coefficients = structure(c(1.47191076131574, 0.586694550701453, NA, 0.258706725324317), .Names = c('(Intercept)', 'x1', 'x2', 'x3')), residuals = structure(c(0.224762433374997, 0.4813346401898, -0.548705796690786, -0.873306430909872, 0.3255545927283, -0.288240908441576, 0.530823516045489, -0.0649703574297026, 1.2699009772491, -1.05715266611575), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10')), effects = structure(c(-18.0083860263211, 7.91372047070235, 0.594462796282497, -0.733976126666906, 0.546582698364345, -0.032332374655677, 0.774795104738016, 0.120246912926227, 1.34954655602521, -1.1298961521627), .Names = c('(Intercept)', 'x1', 'x3', '', '', '', '', '', '', '')), rank = 3L, fitted.values = structure(c(2.08447598454963, 2.74878255284838, 3.46483046621199, 4.23261972464046, 5.0521503281338, 5.923422276692, 6.84643557031507, 7.821190209003, 8.84768619275579, 9.92592352157344), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10')), assign = 0:3, qr = structure(list( qr = structure(c(-3.16227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, -17.3925271309261, 9.08295106229247, 0.15621147358221, 0.0461150970695743, -0.0639812794430617, -0.174077655955698, -0.284174032468334, -0.39427040898097, -0.504366785493606, -0.614463162006242, -12.1747689916483, 9.99124616852172, 2.29782505861521, 0.388354773181155, 0.471167347118467, 0.46694109307793, 0.375676011059543, 0.197372101063308, -0.0679706369107753, -0.420352202862709, -17.3925271309261, 9.08295106229247, 1.30962518065979e-16, -1.00907321685019e-15, 0.0501848681992808, -0.170313338748631, 0.0400139169574381, -0.419073670426332, -0.887431917453648, -0.0447724572319277), .Dim = c(10L, 4L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10'), c('(Intercept)', 'x1', 'x3', 'x2')), assign = 0:3), qraux = c(1.31622776601684, 1.26630785009485, 1.21850337126599, 1.04136435435488 ), pivot = c(1L, 2L, 4L, 3L), tol = 1e-07, rank = 3L), .Names = c('qr', 'qraux', 'pivot', 'tol', 'rank'), class = 'qr'), df.residual = 7L, xlevels = structure(list(), .Names = character(0)), call = quote(lm(formula = y ~ x1 + x2 + x3)), terms = quote(y ~ x1 + x2 + x3), model = structure(list(y = c(2.30923841792462, 3.23011719303818, 2.9161246695212, 3.35931329373059, 5.3777049208621, 5.63518136825043, 7.37725908636056, 7.75621985157329, 10.1175871700049, 8.86877085545769), x1 = 1:10, x2 = 1:10, x3 = c(0.1, 0.4, 0.9, 1.6, 2.5, 3.6, 4.9, 6.4, 8.1, 10)), .Names = c('y', 'x1', 'x2', 'x3'), terms = quote(y ~ x1 + x2 + x3), row.names = c(NA, 10L), class = 'data.frame')), .Names = c('coefficients', 'residuals', 'effects', 'rank', 'fitted.values', 'assign', 'qr', 'df.residual', 'xlevels', 'call', 'terms', 'model'), class = 'lm'));`(`(argv[[1]]);"); + assertEval("argv <- list(structure(list(coefficients = structure(c(1.47191076131574, 0.586694550701453, NA, 0.258706725324317), .Names = c('(Intercept)', 'x1', 'x2', 'x3')), residuals = structure(c(0.224762433374997, 0.4813346401898, -0.548705796690786, -0.873306430909872, 0.3255545927283, -0.288240908441576, 0.530823516045489, -0.0649703574297026, 1.2699009772491, -1.05715266611575), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10')), effects = structure(c(-18.0083860263211, 7.91372047070235, 0.594462796282497, -0.733976126666906, 0.546582698364345, -0.032332374655677, 0.774795104738016, 0.120246912926227, 1.34954655602521, -1.1298961521627), .Names = c('(Intercept)', 'x1', 'x3', '', '', '', '', '', '', '')), rank = 3L, fitted.values = structure(c(2.08447598454963, 2.74878255284838, 3.46483046621199, 4.23261972464046, 5.0521503281338, 5.923422276692, 6.84643557031507, 7.821190209003, 8.84768619275579, 9.92592352157344), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10')), assign = 0:3, qr = structure(list( qr = structure(c(-3.16227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, -17.3925271309261, 9.08295106229247, 0.15621147358221, 0.0461150970695743, -0.0639812794430617, -0.174077655955698, -0.284174032468334, -0.39427040898097, -0.504366785493606, -0.614463162006242, -12.1747689916483, 9.99124616852172, 2.29782505861521, 0.388354773181155, 0.471167347118467, 0.46694109307793, 0.375676011059543, 0.197372101063308, -0.0679706369107753, -0.420352202862709, -17.3925271309261, 9.08295106229247, 1.30962518065979e-16, -1.00907321685019e-15, 0.0501848681992808, -0.170313338748631, 0.0400139169574381, -0.419073670426332, -0.887431917453648, -0.0447724572319277), .Dim = c(10L, 4L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10'), c('(Intercept)', 'x1', 'x3', 'x2')), assign = 0:3), qraux = c(1.31622776601684, 1.26630785009485, 1.21850337126599, 1.04136435435488 ), pivot = c(1L, 2L, 4L, 3L), tol = 1e-07, rank = 3L), .Names = c('qr', 'qraux', 'pivot', 'tol', 'rank'), class = 'qr'), df.residual = 7L, xlevels = structure(list(), .Names = character(0)), call = quote(lm(formula = y ~ x1 + x2 + x3)), terms = quote(y ~ x1 + x2 + x3), model = structure(list(y = c(2.30923841792462, 3.23011719303818, 2.9161246695212, 3.35931329373059, 5.3777049208621, 5.63518136825043, 7.37725908636056, 7.75621985157329, 10.1175871700049, 8.86877085545769), x1 = 1:10, x2 = 1:10, x3 = c(0.1, 0.4, 0.9, 1.6, 2.5, 3.6, 4.9, 6.4, 8.1, 10)), .Names = c('y', 'x1', 'x2', 'x3'), terms = quote(y ~ x1 + x2 + x3), row.names = c(NA, 10L), class = 'data.frame')), .Names = c('coefficients', 'residuals', 'effects', 'rank', 'fitted.values', 'assign', 'qr', 'df.residual', 'xlevels', 'call', 'terms', 'model'), class = 'lm'));`(`(argv[[1]]);"); } @Test @@ -1622,8 +1621,7 @@ public class TestBuiltin_operators extends TestBase { @Test public void testoperators324() { - assertEval(Ignored.Unknown, - "argv <- list(c(0, 0, 0, 0, 0, 0, 4.94065645841247e-324, 0, 0, 0, 0, 0), structure(c(73.0102287440125, 79.6161885135717, 81.5497837663961, 53.9710956454646, 43.6831159601594, 20.8581884349194, 7.6155030786098, 10.8008470888011, 14.7201505829463, 8.49167208457355, 101.686214382123, 921.711710792497), .Names = c('1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1')));`%*%`(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(c(0, 0, 0, 0, 0, 0, 4.94065645841247e-324, 0, 0, 0, 0, 0), structure(c(73.0102287440125, 79.6161885135717, 81.5497837663961, 53.9710956454646, 43.6831159601594, 20.8581884349194, 7.6155030786098, 10.8008470888011, 14.7201505829463, 8.49167208457355, 101.686214382123, 921.711710792497), .Names = c('1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1')));`%*%`(argv[[1]],argv[[2]]);"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_order.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_order.java index 0ae5ec00e3e78270807e7a889fa46c07c60b6411..c9fd1e66c528a19b8c3428e924043b95eb401e2e 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_order.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_order.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -162,5 +162,7 @@ public class TestBuiltin_order extends TestBase { assertEval("{ order(c(0/0, -1/0, 2), na.last=NA) }"); assertEval("order(c('40 50', '405', '40 51', '4028', '40 20', '40 30', '404'))"); + + assertEval("order(c(1,2,0), decreasing=NA)"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parse.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parse.java index bee6607ab3cf968740191301de0ff56c2facb8a3..62df5804911e76c34d4d27ceab29b143a06716da 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parse.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parse.java @@ -36,7 +36,7 @@ public class TestBuiltin_parse extends TestBase { @Test public void testParseDataFrame() { - assertEval(Ignored.ImplementationError, "eval(parse(text=deparse(data.frame(x=c(1)))))"); + assertEval("eval(parse(text=deparse(data.frame(x=c(1)))))"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pathexpand.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pathexpand.java index 000d12c09fec9d6ff3992dda94035b761e426568..0b873424d18b832deaa51e573156d5bd30148e69 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pathexpand.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pathexpand.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. */ @@ -39,7 +39,7 @@ public class TestBuiltin_pathexpand extends TestBase { @Test public void testArgsValidation() { - assertEval(Output.IgnoreErrorContext, "path.expand(NULL)"); - assertEval(Output.IgnoreErrorContext, "path.expand(42)"); + assertEval("path.expand(NULL)"); + assertEval("path.expand(42)"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java index d88d8ba6957cb9c134ce6025dd02968fee4bfe6c..53fd3e3a1287415a5b8a0ff85f010c63b9fdcff0 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.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. */ @@ -61,8 +61,11 @@ public class TestBuiltin_pmatch extends TestBase { public void testArgumentsCasts() { assertEval("pmatch(NULL, 1)"); assertEval("pmatch(1, NULL)"); + assertEval("pmatch(x=NULL, table=NULL)"); + assertEval("pmatch(x=1)"); + assertEval("pmatch(table=1)"); assertEval("pmatch(1:5, c(1,3), nomatch=NULL)"); - assertEval(Output.IgnoreWarningContext, "pmatch(1:5, c(1,3), nomatch='str')"); + assertEval("pmatch(1:5, c(1,3), nomatch='str')"); assertEval("pmatch(1:5, c(1,3), duplicates.ok=42)"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java index ad1b4881befa12c6d22d789f5d5321bd8a690647..426e2c4d77e9106fd6e67556d83862f35deb44e2 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -91,19 +91,19 @@ public class TestBuiltin_pmax extends TestBase { public void testPMax() { assertEval("{ pmax(c(1L, 7L), c(42L, 1L)) }"); assertEval("{ pmax(c(1L, 7L), integer()) }"); - assertEval(Output.IgnoreWarningContext, "{ pmax(c(1L, 7L, 8L), c(1L), c(42L, 1L)) }"); + assertEval("{ pmax(c(1L, 7L, 8L), c(1L), c(42L, 1L)) }"); assertEval("{ pmax(c(1L, 7L), c(42L, as.integer(NA))) }"); assertEval("{ pmax(c(1L, 7L), c(42L, as.integer(NA)), na.rm=TRUE) }"); assertEval("{ pmax(c(1, 7), c(42, 1)) }"); assertEval("{ pmax(c(1, 7), double()) }"); - assertEval(Output.IgnoreWarningContext, "{ pmax(c(1, 7, 8), c(1), c(42, 1)) }"); + assertEval("{ pmax(c(1, 7, 8), c(1), c(42, 1)) }"); assertEval("{ pmax(c(1, 7), c(42, as.double(NA))) }"); assertEval("{ pmax(c(1, 7), c(42, as.double(NA)), na.rm=TRUE) }"); assertEval("{ pmax(c(\"1\", \"7\"), c(\"42\", \"1\")) }"); assertEval("{ pmax(c(\"1\", \"7\"), character()) }"); - assertEval(Output.IgnoreWarningContext, "{ pmax(c(\"1\", \"7\", \"8\"), c(\"1\"), c(\"42\", \"1\")) }"); + assertEval("{ pmax(c(\"1\", \"7\", \"8\"), c(\"1\"), c(\"42\", \"1\")) }"); assertEval("{ pmax(c(\"1\", \"7\"), c(\"42\", as.character(NA))) }"); assertEval("{ pmax(c(\"1\", \"7\"), c(\"42\", as.character(NA)), na.rm=TRUE) }"); assertEval("{ pmax(c(\"1\", as.character(NA)), c(\"42\", \"1\"), na.rm=TRUE) }"); @@ -113,7 +113,7 @@ public class TestBuiltin_pmax extends TestBase { assertEval("{ pmax(c(FALSE, TRUE), logical()) }"); assertEval("{ pmax(c(FALSE, TRUE), c(FALSE, NA)) }"); - assertEval(Output.IgnoreErrorContext, "{ pmax(as.raw(42)) }"); - assertEval(Output.IgnoreErrorContext, "{ pmax(7+42i) }"); + assertEval("{ pmax(as.raw(42)) }"); + assertEval("{ pmax(7+42i) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java index 28c1a51ff1840c44ee62e6e5d46db9ec687c66f3..d3624ecd3aed2d43da2608058ee9cc386fea9421 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -76,19 +76,19 @@ public class TestBuiltin_pmin extends TestBase { public void testPMin() { assertEval("{ pmin(c(1L, 7L), c(42L, 1L)) }"); assertEval("{ pmin(c(1L, 7L), integer()) }"); - assertEval(Output.IgnoreWarningContext, "{ pmin(c(1L, 7L, 8L), c(1L), c(42L, 1L)) }"); + assertEval("{ pmin(c(1L, 7L, 8L), c(1L), c(42L, 1L)) }"); assertEval("{ pmin(c(1L, 7L), c(42L, as.integer(NA))) }"); assertEval("{ pmin(c(1L, 7L), c(42L, as.integer(NA)), na.rm=TRUE) }"); assertEval("{ pmin(c(1, 7), c(42, 1)) }"); assertEval("{ pmin(c(1, 7), double()) }"); - assertEval(Output.IgnoreWarningContext, "{ pmin(c(1, 7, 8), c(1), c(42, 1)) }"); + assertEval("{ pmin(c(1, 7, 8), c(1), c(42, 1)) }"); assertEval("{ pmin(c(1, 7), c(42, as.double(NA))) }"); assertEval("{ pmin(c(1, 7), c(42, as.double(NA)), na.rm=TRUE) }"); assertEval("{ pmin(c(\"1\", \"7\"), c(\"42\", \"1\")) }"); assertEval("{ pmin(c(\"1\", \"7\"), character()) }"); - assertEval(Output.IgnoreWarningContext, "{ pmin(c(\"1\", \"7\", \"8\"), c(\"1\"), c(\"42\", \"1\")) }"); + assertEval("{ pmin(c(\"1\", \"7\", \"8\"), c(\"1\"), c(\"42\", \"1\")) }"); assertEval("{ pmin(c(\"1\", \"7\"), c(\"42\", as.character(NA))) }"); assertEval("{ pmin(c(\"1\", \"7\"), c(\"42\", as.character(NA)), na.rm=TRUE) }"); assertEval("{ pmin(c(\"1\", as.character(NA)), c(\"42\", \"1\"), na.rm=TRUE) }"); @@ -98,8 +98,8 @@ public class TestBuiltin_pmin extends TestBase { assertEval("{ pmin(c(FALSE, TRUE), logical()) }"); assertEval("{ pmin(c(FALSE, TRUE), c(FALSE, NA)) }"); - assertEval(Output.IgnoreErrorContext, "{ pmin(as.raw(42)) }"); - assertEval(Output.IgnoreErrorContext, "{ pmin(7+42i) }"); + assertEval("{ pmin(as.raw(42)) }"); + assertEval("{ pmin(7+42i) }"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_primUntrace.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_primUntrace.java index 67ced8d5a6895c962b9285c87485d60b8a411db1..d910a6cdea4ecf04534599ca5eab08d3393eb52d 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_primUntrace.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_primUntrace.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. */ @@ -24,6 +24,6 @@ public class TestBuiltin_primUntrace extends TestBase { @Test public void testArgsCasts() { - assertEval(Output.IgnoreErrorContext, ".primUntrace(42)"); + assertEval(".primUntrace(42)"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_print.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_print.java index afd022da35facf0571e360ce9fb49bc5ec857b7f..4cbcb19b59ac5316b85feda8637ff7ec7aa44b43 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_print.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_print.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -43,9 +43,8 @@ public class TestBuiltin_print extends TestBase { @Test public void testprint5() { - assertEval(Ignored.Unknown, - "argv <- structure(list(x = structure(list(statistic = structure(0.87901108669074, .Names = 't'), parameter = structure(19, .Names = 'df'), p.value = 0.390376937081292, conf.int = structure(c(-0.332667989442433, 0.814407243771461), conf.level = 0.95), estimate = structure(0.240869627164514, .Names = 'mean of x'), null.value = structure(0, .Names = 'mean'), alternative = 'two.sided', method = 'One Sample t-test', data.name = 'x'), .Names = c('statistic', 'parameter', 'p.value', 'conf.int', 'estimate', 'null.value', 'alternative', 'method', 'data.name'), class = 'htest')), .Names = 'x');" + - "do.call('print', argv)"); + assertEval("argv <- structure(list(x = structure(list(statistic = structure(0.87901108669074, .Names = 't'), parameter = structure(19, .Names = 'df'), p.value = 0.390376937081292, conf.int = structure(c(-0.332667989442433, 0.814407243771461), conf.level = 0.95), estimate = structure(0.240869627164514, .Names = 'mean of x'), null.value = structure(0, .Names = 'mean'), alternative = 'two.sided', method = 'One Sample t-test', data.name = 'x'), .Names = c('statistic', 'parameter', 'p.value', 'conf.int', 'estimate', 'null.value', 'alternative', 'method', 'data.name'), class = 'htest')), .Names = 'x');" + + "do.call('print', argv)"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_printdefault.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_printdefault.java index a70ec7d7b1d4a3d33dc50f60e823b09a95a082f8..1ad5ecd3c4a4c7abecef5810824a8d8a2f2db76c 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_printdefault.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_printdefault.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. */ @@ -29,8 +29,7 @@ public class TestBuiltin_printdefault extends TestBase { @Test public void testprintdefault3() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c('1', '2', '\\\\b', '4', '5', '\\\\040', '\\\\x20', 'c:\\\\spencer\\\\tests', '\\\\t', '\\\\n', '\\\\r'), .Dim = c(11L, 1L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'), 'TEST')), NULL, FALSE, NULL, NULL, TRUE, NULL, TRUE, FALSE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(structure(c('1', '2', '\\\\b', '4', '5', '\\\\040', '\\\\x20', 'c:\\\\spencer\\\\tests', '\\\\t', '\\\\n', '\\\\r'), .Dim = c(11L, 1L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'), 'TEST')), NULL, FALSE, NULL, NULL, TRUE, NULL, TRUE, FALSE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test @@ -50,8 +49,7 @@ public class TestBuiltin_printdefault extends TestBase { @Test public void testprintdefault7() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(NA, NA, NA, 'a', NA, NA, 'b', 'd', NA, '10', '12', '14'), .Dim = 3:4), NULL, TRUE, '----', NULL, TRUE, NULL, TRUE, FALSE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); + assertEval("argv <- list(structure(c(NA, NA, NA, 'a', NA, NA, 'b', 'd', NA, '10', '12', '14'), .Dim = 3:4), NULL, TRUE, '----', NULL, TRUE, NULL, TRUE, FALSE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java index 264a3af783fdfbb7ffb7d99604b181b0788238b5..4adffd95dc83fe4267e26fefa57a2bc8b46a27e7 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -82,6 +82,16 @@ public class TestBuiltin_prod extends TestBase { assertEval("{prod(c(1+2i,1+3i,1+45i))}"); assertEval("{prod(c(TRUE, TRUE))}"); assertEval("{prod(c(TRUE, FALSE))}"); + assertEval("{prod()}"); + assertEval("{prod(NULL)}"); + assertEval("{prod(c())}"); + assertEval("{prod(c(),c())}"); + assertEval("{prod(2+3i,c())}"); + assertEval("{prod(2+3i,42+5i)}"); + assertEval("{prod(2+3i,42)}"); + assertEval("{prod(42,2+3i)}"); + assertEval("{prod('a')}"); + assertEval("{prod(list())}"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_psort.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_psort.java index 3052a9db90e8cf27a4761ce9c2da0215961b3a88..ae148fb1ac5690446df385b2f86cdd75e0446a02 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_psort.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_psort.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. */ @@ -92,4 +92,12 @@ public class TestBuiltin_psort extends TestBase { public void testpsort14() { assertEval("argv <- list(c(-1.36919169254062, -0.667819876370237, -0.253162069270378, -0.0834190388782434, -0.00786394222146348, 0.0246733498130512, 0.0730305465518564, 0.0881443844426084, 0.170711734013213, 0.552921941721332), c(1L, 3L, 4L, 5L, 6L, 7L, 8L, 10L)); .Internal(psort(argv[[1]], argv[[2]]))"); } + + @Test + public void testArgsCasts() { + assertEval("{ .Internal(psort(as.raw(c(0x44,0x40)), FALSE)) }"); // Only numeric vectors can + // be sorted + assertEval("{ .Internal(sort(NULL, FALSE)) }"); + assertEval("{ lv<-list(a=5,b=c(1,2)); .Internal(sort(lv,FALSE)) }"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qr.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qr.java index a4e57175ddfa4f8ff1d9b0ee8fb0332a803cec65..397aa78e82d932bdeac49e10adb8ba784e70900b 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qr.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qr.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -44,7 +44,7 @@ public class TestBuiltin_qr extends TestBase { assertEval(Ignored.Unknown, "{ round( qr(matrix(1:6,nrow=2), LAPACK=TRUE)$qr, digits=5) }"); // qr.coef - assertEval(Output.IgnoreErrorContext, "{ x <- qr(cbind(1:10,2:11), LAPACK=TRUE) ; qr.coef(x, 1:2) }"); + assertEval("{ x <- qr(cbind(1:10,2:11), LAPACK=TRUE) ; qr.coef(x, 1:2) }"); assertEval(Ignored.Unknown, " { x <- qr(cbind(1:10,2:11), LAPACK=TRUE) ; round( qr.coef(x, 1:10), digits=5 ) }"); assertEval(Ignored.Unknown, "{ x <- qr(c(3,1,2), LAPACK=TRUE) ; round( qr.coef(x, c(1,3,2)), digits=5 ) }"); // FIXME: GNU-R will print negative zero as zero diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qsort.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qsort.java index 2f586449ad51e2be6965bad423e2b356b218d176..f9676194a0c36444ae1e35dd50404f5285463bd7 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qsort.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qsort.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. */ @@ -82,4 +82,17 @@ public class TestBuiltin_qsort extends TestBase { public void testqsort13() { assertEval("argv <- list(c(63, 187, 64, 188), FALSE); .Internal(qsort(argv[[1]], argv[[2]]))"); } + + @Test + public void testArgsCasts() { + // GnuR "qsort" outputs + // "Error: argument is not a numeric vector" + // for the raw vector while both "sort" and "qsort" in GnuR output + // "Error: raw vectors cannot be sorted" + // We share the same Casts adapter for all "sort","psort" and "qsort" + // so prefixing with ignore the error message here for now. + assertEval(Output.IgnoreErrorMessage, "{ .Internal(qsort(as.raw(c(0x44,0x40)), FALSE)) }"); + assertEval("{ .Internal(sort(NULL, FALSE)) }"); + assertEval("{ lv<-list(a=5,b=c(1,2)); .Internal(sort(lv,FALSE)) }"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_quit.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_quit.java index 28562baadd09d6ca16c269da44e0280629b73ade..7f5b2e17592e54e21bb5a25d2f0df591bc4fd8f9 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_quit.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_quit.java @@ -64,7 +64,7 @@ public class TestBuiltin_quit extends TestBase { @Test public void testQuitErrorSave() { - assertEval("{ quit(\"xx\") }"); + assertEval(Output.ImprovedErrorContext, "{ quit(\"xx\") }"); } @Test @@ -75,7 +75,7 @@ public class TestBuiltin_quit extends TestBase { /** * Removes temporarily created files {@code .RData} and {@code .Rhistory} and restore backups if * available. - * + * * @throws IOException */ @AfterClass diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_quote.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_quote.java index 19382e734f72edfc36f0e50fb905ddd51a288cb8..2eeee8079985c3634978268e7e77c3010d67cfdf 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_quote.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_quote.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -41,5 +41,9 @@ public class TestBuiltin_quote extends TestBase { assertEval("quote(??show)"); assertEval("quote(?`[[`)"); assertEval("quote(?'+')"); + + // in GNUR, these behave inconsistently: + assertEval(Ignored.ImplementationError, "quote()"); + assertEval("quote(expr=)"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java index e15b21ddd44e6d74bbb05bfb1eed47b911f40924..df9b448fc350c061c00b4067050b32ad0d61c264 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -112,6 +112,12 @@ public class TestBuiltin_rep extends TestBase { assertEval("argv <- list(FALSE, 1L); .Internal(rep_len(argv[[1]], argv[[2]]))"); } + @Test + public void testRepLenNull() { + assertEval("rep_len(NULL,0)"); + assertEval("rep_len(NULL,2)"); + } + @Test public void testrep21() { assertEval("argv <- structure(list(1:5, each = 2), .Names = c('', 'each'));do.call('rep', argv)"); @@ -205,10 +211,10 @@ public class TestBuiltin_rep extends TestBase { assertEval("{ rep(7, times=NULL) }"); assertEval("{ rep(7, times=\"7\") }"); assertEval("{ rep(7, length.out=\"7\") }"); - assertEval(Output.IgnoreWarningContext, "{ rep(7, length.out=integer()) }"); + assertEval("{ rep(7, length.out=integer()) }"); assertEval("{ rep(7, length.out=NA) }"); assertEval("{ rep(7, length.out=NULL) }"); - assertEval(Output.IgnoreWarningContext, "{ rep(7, length.out=c(7, 42)) }"); + assertEval("{ rep(7, length.out=c(7, 42)) }"); assertEval("{ rep(7, each=\"7\") }"); assertEval("{ rep(7, each=integer()) }"); assertEval("{ rep(7, each=NA) }"); @@ -218,5 +224,12 @@ public class TestBuiltin_rep extends TestBase { assertEval("{ rep(7, times=-1) }"); assertEval("{ rep(c(7, 42), times=c(2, NA)) }"); assertEval(Output.IgnoreWarningContext, "{ rep(7, times=\"foo\") }"); + + assertEval("v <- 1; class(v) <- 'asdf'; names(v) <- 'asdf'; rep(v, 1)"); + assertEval("v <- 1; class(v) <- 'asdf'; names(v) <- 'asdf'; rep(v, 2)"); + assertEval("v <- 1; names(v) <- 'asdf'; rep(v, 1)"); + assertEval("v <- 1; names(v) <- 'asdf'; rep(v, 2)"); + assertEval("v <- 1; class(v) <- 'asdf'; rep(v, 1)"); + assertEval("v <- 1; class(v) <- 'asdf'; rep(v, 2)"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java index c634f9bcf0ba0af38f727a6d98142f9ef0bc52b6..c6a77e41ad28e7ee7b8154f1a62639f6943249f0 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -164,14 +164,27 @@ public class TestBuiltin_repint extends TestBase { assertEval("{ rep.int(c(1,2,3),c(2,8,3)) }"); assertEval("{ rep.int(seq_len(2), rep.int(8, 2)) }"); - assertEval(Output.IgnoreErrorContext, "{ rep.int(c(1,2,3),c(2,8)) }"); + assertEval("{ rep.int(c(1,2,3),c(2,8)) }"); assertEval(Output.IgnoreErrorContext, "{ rep.int(function() 42, 7) }"); assertEval("{ rep.int(7, character()) }"); assertEval("{ rep.int(7, NULL) }"); assertEval("{ rep.int(7, \"7\") }"); - assertEval(Output.IgnoreErrorContext, "{ rep.int(7, c(7, 42)) }"); + assertEval("{ rep.int(7, c(7, 42)) }"); assertEval("{ rep_int(7, function() 42) }"); - assertEval(Output.IgnoreErrorContext, "{ rep.int(7, NA) }"); + assertEval("{ rep.int(7, NA) }"); + assertEval("{ rep.int(7, -4) }"); + assertEval("{ rep.int(c(7,1), c(1,-4)) }"); + assertEval("{ rep.int(c(7,1), c(1,4,5)) }"); } + + @Test + public void testRepIntComplex() { + assertEval("{ rep.int(c(1+2i,20+30i,100-400i), 2) }"); + assertEval("{ rep.int(c(1+2i,100-400i,20+30i), c(3,7,2)) }"); + assertEval("{ rep.int(c(1+2i,20+30i,100-400i), -3) }"); + assertEval("{ rep.int(c(1+2i,100-400i,20+30i), c(3,7)) }"); + assertEval("{ rep.int(c(1+2i,100-400i,20+30i), c(3,-7)) }"); + } + } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rhyper.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rhyper.java new file mode 100644 index 0000000000000000000000000000000000000000..dbe91a4bc2125a9cc1150d5bc173431184526049 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rhyper.java @@ -0,0 +1,41 @@ +/* + * 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.builtins; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestBuiltin_rhyper extends TestBase { + + @Test + public void testSimple() { + assertEval("rhyper(0,0,0,0)"); + } + + @Test + public void testNullAndMissing() { + assertEval("rmultinom(0,0,0,NULL)"); + assertEval("rmultinom(0,0,0)"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rmultinom.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rmultinom.java new file mode 100644 index 0000000000000000000000000000000000000000..caa8e9c018ea181c93433ad33e6754f24fdaa697 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rmultinom.java @@ -0,0 +1,41 @@ +/* + * 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.builtins; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestBuiltin_rmultinom extends TestBase { + + @Test + public void testSimple() { + assertEval("rmultinom(1,1,1)"); + } + + @Test + public void testNullAndMissing() { + assertEval("rmultinom(1, 1, NULL)"); + assertEval("rmultinom(1, 1)"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowsum.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowsum.java index 9e5d90ea9425a6cfdf0c225f88665c730b832808..7179dd4688cc195e3ef3a97b63466c68a27087ab 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowsum.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowsum.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. */ @@ -58,4 +58,23 @@ public class TestBuiltin_rowsum extends TestBase { public void testrowsum8() { assertEval("argv <- list(structure(c(1.33333333333333, -1.33333333333333, 1, 1.33333333333333, -2, 0.666666666666667, -0.666666666666667, 0.666666666666667, -0.666666666666667), .Dim = c(9L, 1L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9'), 'x')), structure(c(1, 1, 2, 2, 2, 2, 3, 4, 5), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9')), c(1, 2, 3, 4, 5), FALSE, c('1', '2', '3', '4', '5')); .Internal(rowsum_matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))"); } + + @Test + public void testRowsumArgCoverage() { + assertEval("x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, ug, FALSE, as.character(ug)))"); + // 2nd parm function => GnuR Error: segfault + assertEvalFastR("{ x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, print, ug, FALSE, as.character(ug))); }", + "cat(\"Error in rowsum_matrix(x, print, ug, FALSE, as.character(ug)) :\\n invalid 'g' argument\""); + // 3rd parm is function => GnuR Error: "Error: unimplemented type 'closure' in + // 'HashTableSetup'" + assertEval(Output.IgnoreErrorMessage, "x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, print, FALSE, as.character(ug)))"); + // 2nd parm NULL => GnuR Error: segfault\n" + + assertEvalFastR("x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, NULL, ug, FALSE,as.character(ug)))", + "cat(\"Error in rowsum_matrix(x, NULL, ug, FALSE, as.character(ug)) :\\n invalid 'g' argument\""); + // 3rd parm NULL => GnuR Error: Error: unimplemented type 'NULL' in 'HashTableSetup' + assertEval(Output.IgnoreErrorMessage, "x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, NULL, FALSE,as.character(ug)))"); + assertEval(Output.IgnoreErrorMessage, "x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, , ug, FALSE,as.character(ug)))"); + assertEval(Output.IgnoreErrorMessage, "x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, , FALSE,as.character(ug)))"); + } + } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java index fa5190ed610d8497b50dd3f3a2ff5186322223d2..e15202aaa8a4d4ea5fc6978def95d1a80d7f0f84 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -81,6 +81,11 @@ public class TestBuiltin_sample extends TestBase { assertEval("set.seed(42); .Internal(sample(4.5e20, 4.5e20, FALSE, NULL))"); assertEval("set.seed(42); .Internal(sample(NA, NA, FALSE, NULL))"); assertEval("set.seed(42); .Internal(sample(NaN, NaN, FALSE, NULL))"); + assertEval("set.seed(42); .Internal(sample(NULL, NULL, F, NULL))"); + assertEval("set.seed(42); .Internal(sample(NULL, NULL, F, seq(1.2,3)))"); + assertEval(Output.IgnoreErrorMessage, "set.seed(42); .Internal(sample(5,6,T,))"); + assertEval("set.seed(42); .Internal(sample(5,6,T,NULL))"); + assertEval(Output.IgnoreErrorMessage, "set.seed(42); .Internal(sample(5,6,T,seq(1.2,3)))"); // Note: we treat Infinity in NaN check assertEval(Output.IgnoreErrorMessage, "set.seed(42); .Internal(sample(1/0, 1, FALSE, NULL))"); // size @@ -93,12 +98,12 @@ public class TestBuiltin_sample extends TestBase { assertEval("set.seed(42); sample(2, 0)"); assertEval("set.seed(42); sample(0, 0)"); // replace - assertEval(Output.IgnoreErrorContext, "set.seed(42); sample(4, replace=c(T,F))"); + assertEval("set.seed(42); sample(4, replace=c(T,F))"); assertEval("set.seed(42); sample(4, replace=1)"); assertEval("set.seed(42); sample(4, replace=1.2)"); assertEval(Output.IgnoreErrorMessage, "set.seed(42); sample(4, replace='s')"); // prob - assertEval(Output.IgnoreErrorContext, "set.seed(42); sample(4, prob=c(1,2))"); - assertEval(Output.IgnoreErrorContext, "set.seed(42); sample(4, prob=c(-1,1,1,2))"); + assertEval("set.seed(42); sample(4, prob=c(1,2))"); + assertEval("set.seed(42); sample(4, prob=c(-1,1,1,2))"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample2.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample2.java index 36d5e2badf790194780ecb5bcc512e624cc54544..bd9ea049bb74e0012a9e965b9ee2f341822600b6 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample2.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -35,6 +35,7 @@ public class TestBuiltin_sample2 extends TestBase { assertEval("set.seed(42); x <- .Internal(sample2(10L, 3L)); y <- .Internal(sample2(10L, 3L)); list(x, y); "); // test with n > MAX_INT assertEval("set.seed(42); .Internal(sample2(4147483647, 10))"); + assertEval("set.seed(42); .Internal(sample2(NULL,3))"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java index ad62fe7e4e8e1b1328d6e33c236162215bd4086b..fd9a88eff65be0af9a6672162f4f6e7f5102d351 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -24,16 +24,16 @@ public class TestBuiltin_scan extends TestBase { assertEval("{ con<-textConnection(c(\"TITLE extra line\", \"2 3 5 7\", \"11 13 17\")); scan(con, skip = 1, quiet = TRUE) }"); assertEval("{ con<-textConnection(c(\"TITLE extra line\", \"2 3 5 7\", \"11 13 17\")); scan(con, skip = 1) }"); assertEval("{ con<-textConnection(c(\"TITLE extra line\", \"2 3 5 7\", \"11 13 17\")); scan(con, skip = 1, nlines = 1) }"); - assertEval(Output.IgnoreWarningContext, "{ con<-textConnection(c(\"TITLE extra line\", \"2 3 5 7\", \"11 13 17\")); scan(con, what = list(\"\",\"\",\"\")) }"); + assertEval("{ con<-textConnection(c(\"TITLE extra line\", \"2 3 5 7\", \"11 13 17\")); scan(con, what = list(\"\",\"\",\"\")) }"); assertEval("{ con<-textConnection(c(\"TITLE extra line\", \"2 3 5 7\", \"11 13 17\")); scan(con, what = list(\"\",\"\",\"\"), flush=TRUE) }"); assertEval("{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, skip = 1) }"); assertEval("{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, skip = 1, quiet=TRUE) }"); assertEval("{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, skip = 1, nlines = 1) }"); - assertEval(Output.IgnoreWarningContext, "{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, what = list(\"\",\"\",\"\")) }"); + assertEval("{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, what = list(\"\",\"\",\"\")) }"); assertEval("{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, what = list(\"\",\"\",\"\"), fill=TRUE) }"); - assertEval(Output.IgnoreErrorContext, "{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, what = list(\"\",\"\",\"\"), multi.line=FALSE) }"); + assertEval("{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, what = list(\"\",\"\",\"\"), multi.line=FALSE) }"); assertEval("{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, what = list(\"\",\"\",\"\"), fill=TRUE, multi.line=FALSE) }"); assertEval("{ con<-textConnection(c(\"\\\"2\\\"\", \"\\\"11\\\"\")); scan(con, what=list(\"\")) }"); @@ -48,5 +48,23 @@ public class TestBuiltin_scan extends TestBase { assertEval("{ con<-textConnection(c(\"bar'foo'\")); scan(con, what=list(\"\")) }"); assertEval("{ con<-textConnection(c(\"'foo'\")); scan(con, what=list(\"\")) }"); assertEval("{ con<-textConnection(c(\"bar 'foo'\")); scan(con, what=list(\"\")) }"); + + // sep should not be treated as a regex: + assertEval("con <- textConnection(\"A|B|C\\n1|2|3\\n4|5|6\"); read.csv(con, sep=\"|\")"); + } + + @Test + public void testArgsCasts() { + // Empty 2nd 'what' parameter + assertEval(Output.IgnoreErrorContext, "{ con<-textConnection(c(\"1 2 3\", \"4 5 6\")); .Internal(scan(con, , 2, ' ', '.', '\"', 0, 3, \"NA\", F, F, F, T, T, '', '#', T, 'utf8', F)) }"); + // NULL 2nd 'what' parameter + assertEval("{ con<-textConnection(c(\"1 2 3\", \"4 5 6\")); .Internal(scan(con, NULL, 2, ' ', '.', '\"', 0, 3, \"NA\", F, F, F, T, T, '', '#', T, 'utf8', F)) }"); + // function passed as 2nd 'what' parameter + assertEval("{ con<-textConnection(c(\"1 2 3\", \"4 5 6\")); .Internal(scan(con, print, 2, ' ', '.', '\"', 0, 3, \"NA\", F, F, F, T, T, '', '#', T, 'utf8', F)) }"); + // NULL 4th 'sep' parameter + assertEval("{ con<-textConnection(c(\"1 2 3\", \"4 5 6\")); .Internal(scan(con, 1L, 2, NULL, '.', '\"', 0, 3, \"NA\", F, F, F, T, T, '', '#', T, 'utf8', F)) }"); + // NULL 5th 'dec' parameter + assertEval("{ con<-textConnection(c(\"1.5 2.89 3\", \"4 5 6\")); .Internal(scan(con, 1.2, 2, ' ', NULL, '\"', 0, 3, \"NA\", F, F, F, T, T, '', '#', T, 'utf8', F)) }"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sep.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sep.java index 3d0a2e63d3117bb4aabfaba4f442b204a20c3dd1..25ebda8276975a0fe55c8648920960c8249eb5db 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sep.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sep.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. */ @@ -64,8 +64,7 @@ public class TestBuiltin_sep extends TestBase { @Test public void testsep10() { - assertEval(Ignored.Unknown, - "argv <- list(c(0, 9.88131291682493e-324, 1.03753785626662e-322, 1.02271588689138e-321, 1.02320995253722e-320, 1.02330876566639e-319, 1.02329394369701e-318, 1.02329295556572e-317, 1.02329300497229e-316, 1.02329299015032e-315, 1.02329299212658e-314, 1.0232929922748e-313, 1.02329299227974e-312, 1.02329299228073e-311, 1.02329299228073e-310, 1.02329299228073e-309, 1.02329299228073e-308, 1.02329299228073e-307), 1.02329299228075);`/`(argv[[1]],argv[[2]]);"); + assertEval("argv <- list(c(0, 9.88131291682493e-324, 1.03753785626662e-322, 1.02271588689138e-321, 1.02320995253722e-320, 1.02330876566639e-319, 1.02329394369701e-318, 1.02329295556572e-317, 1.02329300497229e-316, 1.02329299015032e-315, 1.02329299212658e-314, 1.0232929922748e-313, 1.02329299227974e-312, 1.02329299228073e-311, 1.02329299228073e-310, 1.02329299228073e-309, 1.02329299228073e-308, 1.02329299228073e-307), 1.02329299228075);`/`(argv[[1]],argv[[2]]);"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_along.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_along.java index afa9fbc4c185d0993242d34ba01b71b61c9e5945..e71494b48a9b932dbed42640ad664c807880a1fe 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_along.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_along.java @@ -137,11 +137,9 @@ public class TestBuiltin_seq_along extends TestBase { assertEval("{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) 42; seq_along(x) }"); assertEval("{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) c(100, 200); seq_along(x) }"); assertEval("{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) '48'; seq_along(x) }"); - assertEval("{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) numeric(0); seq_along(x) }"); - assertEval(Output.IgnoreWarningContext, "{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) 'hello world'; seq_along(x) }"); - // length defined in global env should not get us confused: + assertEval(Output.IgnoreWarningContext, Output.IgnoreErrorContext, "{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) numeric(0); seq_along(x) }"); + assertEval(Output.IgnoreWarningContext, Output.IgnoreErrorContext, "{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) 'hello world'; seq_along(x) }"); assertEval("{ length <- function(x) 42; seq_along(c(1,2,3)) }"); - // length in __S3MethodsTable__ should work too assertEval("{ assign('length.myclass', function(...) 42, envir=.__S3MethodsTable__.); x <- 1; class(x) <- 'myclass'; res <- seq_along(x); rm('length.myclass', envir=.__S3MethodsTable__.); res }"); } } 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 31dbe41a622dbb7f5080345f7bdaf9f4e8baada6..3e031ad10ee498a5d31a0b7b12cf40732aa86c79 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -44,6 +44,24 @@ public class TestBuiltin_serialize extends TestBase { assertEval("options(keep.source=FALSE); serialize(quote(111+11), connection=NULL)"); assertEval("options(keep.source=FALSE); serialize(quote(a+b), connection=NULL)"); + assertEval("options(keep.source=FALSE); serialize(TRUE, connection=NULL)"); + assertEval("options(keep.source=FALSE); serialize(FALSE, connection=NULL)"); + assertEval("options(keep.source=FALSE); serialize(c(TRUE, FALSE, TRUE, NA, TRUE), connection=NULL)"); + assertEval("options(keep.source=FALSE); serialize('asdf', connection=NULL)"); + assertEval("options(keep.source=FALSE); serialize(NA_character_, connection=NULL)"); + assertEval("options(keep.source=FALSE); serialize(NA_complex_, connection=NULL)"); + assertEval("options(keep.source=FALSE); serialize(NA_integer_, connection=NULL)"); + assertEval("options(keep.source=FALSE); serialize(NA_real_, connection=NULL)"); + assertEval("options(keep.source=FALSE); serialize(111L, connection=NULL)"); + assertEval("options(keep.source=FALSE); serialize(c(111L, 11L, 990000L, NA_integer_), connection=NULL)"); + assertEval("options(keep.source=FALSE); serialize(111+8i, connection=NULL)"); + assertEval("options(keep.source=FALSE); serialize(c(111+8i, 55+9i, NA), connection=NULL)"); + assertEval("options(keep.source=FALSE); serialize(111, connection=NULL)"); + assertEval("options(keep.source=FALSE); serialize(c(111, 99, NA, 44), connection=NULL)"); + assertEval("options(keep.source=FALSE); serialize(as.raw(10), connection=NULL)"); + assertEval("options(keep.source=FALSE); serialize(as.raw(210), connection=NULL)"); + assertEval("options(keep.source=FALSE); serialize(as.raw(c(1, 55, 210)), connection=NULL)"); + assertEval("options(keep.source=FALSE); serialize(quote((a+b)), connection=NULL)"); assertEval("options(keep.source=FALSE); serialize(quote((a %asdf% b)), connection=NULL)"); @@ -83,5 +101,14 @@ public class TestBuiltin_serialize extends TestBase { assertEval("options(keep.source=FALSE); val <- new.env(hash=FALSE); val$d <- TRUE; serialize(val, connection=NULL)"); assertEval("options(keep.source=FALSE); val <- new.env(hash=FALSE); val$e <- 5+9i; serialize(val, connection=NULL)"); assertEval("options(keep.source=FALSE); val <- new.env(hash=FALSE); val$f <- NA; serialize(val, connection=NULL)"); + + // active bindings + assertEval("options(keep.source=FALSE); val <- new.env(hash=FALSE); makeActiveBinding('a', function(x) print('hello'), val); serialize(val, connection=NULL)"); + assertEval("options(keep.source=FALSE); val <- new.env(hash=FALSE); makeActiveBinding('a', function(x) print('hello'), val); data <- serialize(val, connection=NULL); newenv <- unserialize(rawConnection(data)); newenv$a"); + + assertEval("options(keep.source=FALSE); mc <- setClass('FooSerial0', representation(a = 'call')); obj <- new('FooSerial0'); serialize(obj, connection=NULL)"); + assertEval(Ignored.ImplementationError, "options(keep.source=FALSE); fc <- setClass('FooSerial1', representation(a = 'call')); serialize(fc, connection=NULL)"); + + assertEval("{ options(keep.source=FALSE); f <- function() NULL; attributes(f) <- list(skeleton=quote(`<undef>`())); data <- serialize(f, conn=NULL); unserialize(conn=data) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setS4Object.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setS4Object.java index e12192437ae334b6311f7a951b835eb153b47c8a..e74b1ef0db9e5f3f9a6397ba1b65f688b50b7004 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setS4Object.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setS4Object.java @@ -107,5 +107,6 @@ public class TestBuiltin_setS4Object extends TestBase { assertEval("{ x<-42; asS4(x, TRUE, \"1\") }"); assertEval("{ x<-42; asS4(x, TRUE, logical()) }"); assertEval("{ x<-42; asS4(x, TRUE, c(1,2)) }"); + assertEval("{ x<-42; asS4(, TRUE, 1)) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_shortRowNames.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_shortRowNames.java index 6fc2c7ecc2575d88581e3aff19e0c543c05d8e35..2a5519b8fd6a564b0e0476b3bfc382a93e9caf81 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_shortRowNames.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_shortRowNames.java @@ -129,7 +129,7 @@ public class TestBuiltin_shortRowNames extends TestBase { @Test public void testArgCasts() { - assertEval(Output.IgnoreErrorContext, ".Internal(shortRowNames(42, -2))"); + assertEval(".Internal(shortRowNames(42, -2))"); assertEval(".Internal(shortRowNames(42, '1'))"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sort.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sort.java index e3e5bf0fb2b5787bf1aca33248b5fdd7b763d345..081df3a50526f24182f4493b4f97f4f6d766f137 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sort.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sort.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -125,5 +125,29 @@ public class TestBuiltin_sort extends TestBase { public void testArgsCasts() { assertEval("{ .Internal(sort(c(1L,10L,2L), 'not-numeric')) }"); assertEval("{ .Internal(sort(c(1L,10L,2L), NULL)) }"); + assertEval("{ .Internal(sort(as.raw(c(0x44,0x40)), FALSE)) }"); // Only numeric vectors can + // be sorted + assertEval("{ .Internal(sort(NULL, FALSE)) }"); + assertEval("{ lv<-list(a=5,b=c(1,2)); .Internal(sort(lv,FALSE)) }"); + } + + @Test + public void testQSort() { + assertEval("{ .Internal(qsort(NULL, F)) }"); + assertEval("{ .Internal(qsort(NULL, NULL)) }"); + // seems that when the value provided for decreased is whatever else than FALSE + // then it is interpreted as TRUE. In such a case qsort returns a list containing + // two vectors: the values sorted as in decreased=F and the original indices giving + // the decreased order. NOTE that even though the FastR impl of qsort always returns + // only 1 increasing/decreasing vector, it has no effect on the overall sort function. + assertEval(Ignored.ImplementationError, "{ .Internal(qsort(1, decreased=NULL)) }"); + assertEval(Ignored.ImplementationError, "{ .Internal(qsort(c(4, 2, 3), T)) }"); + assertEval(Ignored.ImplementationError, "{ .Internal(qsort(c(4, 2, 3), 1)) }"); + assertEval(Ignored.ImplementationError, "{ .Internal(qsort(c(4, 2, 3), 'a')) }"); + assertEval(Ignored.ImplementationError, "{ .Internal(qsort(c(4, 2, 3), c('a'))) }"); + assertEval(Ignored.ImplementationError, "{ .Internal(qsort(c(4, 2, 3), list('a'))) }"); + assertEval("{ .Internal(qsort(list(1), F)) }"); + assertEval("{ .Internal(qsort(1, F)) }"); + assertEval("{ .Internal(qsort(c(1), F)) }"); } } 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 46b21139af7ef07f65290793af0453f0edef5163..234bd45d0266926805884872852794e57ed378de 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 @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -36,8 +36,7 @@ public class TestBuiltin_split extends TestBase { @Test public void testsplit4() { - assertEval(Ignored.Unknown, - "argv <- list(structure(c(0, 0, 0, 0, 0, 0, 1.48219693752374e-323, 0, 0, 0, 0, 0), .Dim = c(1L, 12L), .Dimnames = list(NULL, c('1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1'))), structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = '1', class = 'factor')); .Internal(split(argv[[1]], argv[[2]]))"); + assertEval("argv <- list(structure(c(0, 0, 0, 0, 0, 0, 1.48219693752374e-323, 0, 0, 0, 0, 0), .Dim = c(1L, 12L), .Dimnames = list(NULL, c('1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1'))), structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = '1', class = 'factor')); .Internal(split(argv[[1]], argv[[2]]))"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strptime.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strptime.java index 326baff3c47ef3d4c21e235f4873a9470bbdd62f..0c3fa4db12cce8484d2a9ee99aa9fd709684163d 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strptime.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strptime.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. */ @@ -66,4 +66,12 @@ public class TestBuiltin_strptime extends TestBase { public void teststrptime10() { assertEval("argv <- list(c('1937/01/01', '1916/01/01', '1913/01/01', '1927/01/01', '1947/01/01', '1913/01/01', '1917/01/01', '1923/01/01', '1921/01/01', '1926/01/01', '1920/01/01', '1915/01/01', '1914/01/01', '1914/01/01', '1914/01/01', '1919/01/01', '1948/01/01', '1911/01/01', '1909/01/01', '1913/01/01', '1925/01/01', '1926/01/01', '1910/01/01', '1917/01/01', '1936/01/01', '1938/01/01', '1960/01/01', '1915/01/01', '1919/01/01', '1924/01/01', '1914/01/01', '1905/01/01', '1921/01/01', '1929/01/01', '1926/01/01', '1921/01/01', '1908/01/01', '1928/01/01', '1919/01/01', '1921/01/01', '1925/01/01', '1934/01/01', '1927/01/01', '1928/01/01', '1934/01/01', '1922/01/01', '1923/01/01', '1915/01/01', '1934/01/01', '1925/01/01', '1922/01/01', '1930/01/01', '1924/01/01', '1923/01/01', '1919/01/01', '1932/01/01', '1930/01/01', '1923/01/01', '1930/01/01', '1922/01/01', '1919/01/01', '1932/01/01', '1939/01/01', '1923/01/01', '1920/01/01', '1919/01/01', '1952/01/01', '1927/01/01', '1924/01/01', '1919/01/01', '1925/01/01', '1945/01/01', '1916/01/01', '1943/01/01', '1920/01/01', '1920/01/01', '1931/01/01', '1924/01/01', '1919/01/01', '1926/01/01', '1920/01/01', '1952/01/01', '1919/01/01', '1930/01/01', '1925/01/01', '1924/01/01', '1926/01/01', '1918/01/01', '1922/01/01', '1921/01/01', '1925/01/01', '1928/01/01', '1925/01/01', '1929/01/01', '1933/01/01', '1947/01/01', '1950/01/01', '1945/01/01', '1924/01/01', '1939/01/01', '1924/01/01', '1933/01/01', '1928/01/01'), '%Y/%m/%d', ''); .Internal(strptime(argv[[1]], argv[[2]], argv[[3]]))"); } + + @Test + public void testArgsCasts() { + assertEval("{ .Internal(strptime(,'','') }"); + assertEval("{ .Internal(strptime('',,'') }"); + assertEval("{ .Internal(strptime('','',) }"); + } + } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strrep.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strrep.java index 61cf4022fe0298551f50fa20266cd536f29ddfb2..818a0413bd5d0dd396904e6f972134bd0a74caea 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strrep.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strrep.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -34,4 +34,15 @@ public class TestBuiltin_strrep extends TestBase { assertEval("{ strrep(c(\"A\", \"B\", \"C\"), 1 : 3) }"); assertEval("{ strrep(\"X\", 1 : 5) }"); } + + @Test + public void testArgsCasts() { + // GnuR fails with segfault + assertEvalFastR("{ .Internal(strrep(NULL, 5) }", "cat(\"character(0)\")"); + // GnuR - infinite loop + assertEvalFastR("{ .Internal(strrep('aa', NULL) }", "cat(\"character(0)\")"); + assertEval("{ .Internal(strrep(, '') }"); + assertEval("{ .Internal(strrep('', ) }"); + } + } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strsplit.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strsplit.java index 2799e9a5ec964f71a3dcb2d8386ecf7b659e567c..f06f1669ca542addb832b1f4b26154654006cc2e 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strsplit.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strsplit.java @@ -107,8 +107,7 @@ public class TestBuiltin_strsplit extends TestBase { assertEval("{ strsplit(\"ahoj\", split=\"\") [[c(1,2)]] }"); assertEval("{ strsplit(\"a,h,o,j\", split=\",\") }"); assertEval("{ strsplit(\"abc\", \".\", fixed = TRUE, perl=FALSE) }"); - // Warning text formats differently - assertEval(Output.IgnoreWarningContext, "{ strsplit(\"abc\", \".\", fixed = TRUE, perl=TRUE) }"); + assertEval("{ strsplit(\"abc\", \".\", fixed = TRUE, perl=TRUE) }"); assertEval("{ strsplit(\"abc\", \".\", fixed = FALSE, perl=FALSE) }"); assertEval("{ strsplit(\"abc\", \".\", fixed = FALSE, perl=TRUE) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strtrim.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strtrim.java index 00fc2dc52149e953dff0057469a515912a4decb2..6746ef0f1561cff1dfe39b1dff358e6cde831024 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strtrim.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strtrim.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. */ @@ -57,4 +57,10 @@ public class TestBuiltin_strtrim extends TestBase { assertEval("v <- c('a', 'fooooo', 'bbbbbb', 'cccccccccc', 'dd', NA); names(v) <- as.character(1:6); strtrim(v, c(2L, 5L))"); assertEval("v <- c('a', 'fooooo', 'bbbbbb', 'cccccccccc', 'dd', NA); names(v) <- as.character(1:6); strtrim(v, c(2, 5))"); } + + @Test + public void testArgsCasts() { + assertEval(".Internal(strtrim('abc', NULL))"); + assertEval(Output.IgnoreErrorContext, ".Internal(strtrim('abc', ))"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substr.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substr.java index 371431dcb3e1e83b7e9b38b220e9a90fb240aa4d..4a5cff4415a1e82a2f5cb56f8740de80eb885b84 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substr.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substr.java @@ -82,8 +82,8 @@ public class TestBuiltin_substr extends TestBase { assertEval("{ substr(1234L,2,3) }"); assertEval("{ substr(1234,2,3) }"); assertEval("{ substr(\"abcdef\",c(1,2),c(3L,5L)) }"); - assertEval(Output.IgnoreErrorContext, "{ substr(c(\"abcdef\", \"aa\"), integer(), 2) }"); - assertEval(Output.IgnoreErrorContext, "{ substr(c(\"abcdef\", \"aa\"), 2, integer()) }"); + assertEval("{ substr(c(\"abcdef\", \"aa\"), integer(), 2) }"); + assertEval("{ substr(c(\"abcdef\", \"aa\"), 2, integer()) }"); assertEval("{ substr(character(), integer(), integer()) }"); assertEval("{ substr(c(\"abcdef\", \"aa\"), NA, 4) }"); assertEval("{ substr(c(\"abcdef\", \"aa\"), 3, NA) }"); @@ -101,10 +101,12 @@ public class TestBuiltin_substr extends TestBase { assertEval("{ x<-\"abcdef\"; substr(x,1,NA)<-\"0\"; x }"); assertEval("{ x<-character(); substr(x,1,3)<-\"0\"; x }"); assertEval("{ x<-c(\"abcdef\", \"ghijklm\"); substr(x, c(1,NA), 4)<-\"0\"; x }"); - assertEval(Output.IgnoreErrorContext, "{ x<-\"abcdef\"; substr(x,3,1)<-0; x }"); - assertEval(Output.IgnoreErrorContext, "{ x<-\"abcdef\"; substr(x,1,3)<-character(); x }"); - assertEval(Output.IgnoreErrorContext, "{ x<-\"abcdef\"; substr(x,1,3)<-NULL; x }"); - assertEval(Output.IgnoreErrorContext, "{ x<-\"abcdef\"; substr(x,integer(),3)<-NULL; x }"); + + assertEval(Output.ImprovedErrorContext, "{ x<-\"abcdef\"; substr(x,3,1)<-0; x }"); + assertEval(Output.ImprovedErrorContext, "{ x<-\"abcdef\"; substr(x,1,3)<-character(); x }"); + assertEval(Output.ImprovedErrorContext, "{ x<-\"abcdef\"; substr(x,1,3)<-NULL; x }"); + assertEval(Output.ImprovedErrorContext, "{ x<-\"abcdef\"; substr(x,integer(),3)<-NULL; x }"); + assertEval("{ x<-character(); substr(x,1,3)<-0; x }"); assertEval("{ x<-character(); substr(x,1,3)<-NULL; x }"); assertEval("{ x<-character(); substr(x,integer(),3)<-NULL; x }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substrassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substrassign.java index a0a36c9829aac61986ad632c630c303b315b802f..a5e1bdc82233ea2098eb3b21ea9832a26ea7ee07 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substrassign.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substrassign.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. */ @@ -26,4 +26,26 @@ public class TestBuiltin_substrassign extends TestBase { public void testsubstrassign2() { assertEval("argv <- list(c('asfef', 'qwerty', 'yuiop[', 'b', 'stuff.blah.yech'), 2L, 1000000L, c('..', '+++')); .Internal(`substr<-`(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))"); } + + @Test + public void testsubstrassign_1() { + assertEval("argv <- structure(list(x = c('NA', NA, 'BANANA'), start = 1, stop = 2, value = 'na'), .Names = c('x', 'start', 'stop', 'value'));do.call('substr<-', argv)"); + } + + @Test + public void testsubstrassign_2() { + assertEval("argv <- structure(list(x = 'abcde', start = NA, stop = 3, value = 'abc'), .Names = c('x', 'start', 'stop', 'value'));do.call('substr<-', argv)"); + } + + @Test + public void testsubstrassign() { + assertEval("`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), 2, 5, c('a', 'asdf'))"); + assertEval("`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), c(1,10,-6), 5, c('a', 'asdf'))"); + assertEval("`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), 2, c(5,15,-6), c('a', 'asdf'))"); + assertEval("`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), 2, 5, NULL)"); + assertEval("`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), 2, 5, 1)"); + + String[] values = new String[]{"-2L", "-1L", "0L", "1L", "2L"}; + assertEval(template("`substr<-`('ffff', %0, %1, 'xyz')", values, values)); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substrassign_.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substrassign_.java deleted file mode 100644 index 2573d8eefbd23b1659ad77b0f7a35465a905fbe4..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substrassign_.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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) 2014, Purdue University - * Copyright (c) 2014, 2016, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.test.builtins; - -import org.junit.Test; - -import com.oracle.truffle.r.test.TestBase; - -// Checkstyle: stop line length check - -public class TestBuiltin_substrassign_ extends TestBase { - - @Test - public void testsubstrassign_1() { - assertEval("argv <- structure(list(x = c('NA', NA, 'BANANA'), start = 1, stop = 2, value = 'na'), .Names = c('x', 'start', 'stop', 'value'));do.call('substr<-', argv)"); - } - - @Test - public void testsubstrassign_2() { - assertEval("argv <- structure(list(x = 'abcde', start = NA, stop = 3, value = 'abc'), .Names = c('x', 'start', 'stop', 'value'));do.call('substr<-', argv)"); - } -} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sum.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sum.java index 811272afd42a247c5d2955715525e77e5d907825..6fb525be17e257368a45066fa77be511dcce92c1 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sum.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sum.java @@ -178,16 +178,17 @@ public class TestBuiltin_sum extends TestBase { assertEval("{ sum(1+1i,2,NA, na.rm=TRUE) }"); assertEval("sum(v <- 42)"); + assertEval("sum(c(1,2,NA,3), na.rm=NA)"); } @Test public void testOveflow() { assertEval("sum(1:100000)"); assertEval("sum(seq.int(1, 100000))"); - assertEval(Output.IgnoreWarningContext, "sum(seq.int(from=1, by=1, length.out=100000))"); + assertEval("sum(seq.int(from=1, by=1, length.out=100000))"); assertEval("sum(-1:-100000)"); assertEval("sum(seq.int(-1, -100000))"); - assertEval(Output.IgnoreWarningContext, "sum(seq.int(from=-1, by=-1, length.out=100000))"); + assertEval("sum(seq.int(from=-1, by=-1, length.out=100000))"); assertEval("sum(c(2147483647L, 1L))"); assertEval("sum(c(-2147483647L, -1L))"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_summary.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_summary.java index 2d90060ea7e2f86c132865d245075933f9672342..c505c30846a814ee0f0e7118adb8b768f5f7a274 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_summary.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_summary.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. */ @@ -33,8 +33,7 @@ public class TestBuiltin_summary extends TestBase { @Test public void testsummary3() { - assertEval(Ignored.Unknown, - "argv <- structure(list(object = structure(list(Sepal.Length = c(5.1, 4.9, 4.7, 4.6, 5, 5.4, 4.6, 5, 4.4, 4.9, 5.4, 4.8, 4.8, 4.3, 5.8, 5.7, 5.4, 5.1, 5.7, 5.1, 5.4, 5.1, 4.6, 5.1, 4.8, 5, 5, 5.2, 5.2, 4.7, 4.8, 5.4, 5.2, 5.5, 4.9, 5, 5.5, 4.9, 4.4, 5.1, 5, 4.5, 4.4, 5, 5.1, 4.8, 5.1, 4.6, 5.3, 5, 7, 6.4, 6.9, 5.5, 6.5, 5.7, 6.3, 4.9, 6.6, 5.2, 5, 5.9, 6, 6.1, 5.6, 6.7, 5.6, 5.8, 6.2, 5.6, 5.9, 6.1, 6.3, 6.1, 6.4, 6.6, 6.8, 6.7, 6, 5.7, 5.5, 5.5, 5.8, 6, 5.4, 6, 6.7, 6.3, 5.6, 5.5, 5.5, 6.1, 5.8, 5, 5.6, 5.7, 5.7, 6.2, 5.1, 5.7, 6.3, 5.8, 7.1, 6.3, 6.5, 7.6, 4.9, 7.3, 6.7, 7.2, 6.5, 6.4, 6.8, 5.7, 5.8, 6.4, 6.5, 7.7, 7.7, 6, 6.9, 5.6, 7.7, 6.3, 6.7, 7.2, 6.2, 6.1, 6.4, 7.2, 7.4, 7.9, 6.4, 6.3, 6.1, 7.7, 6.3, 6.4, 6, 6.9, 6.7, 6.9, 5.8, 6.8, 6.7, 6.7, 6.3, 6.5, 6.2, 5.9), Sepal.Width = c(3.5, 3, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.4, 3, 3, 4, 4.4, 3.9, 3.5, 3.8, 3.8, 3.4, 3.7, 3.6, 3.3, 3.4, 3, 3.4, 3.5, 3.4, 3.2, 3.1, 3.4, 4.1, 4.2, 3.1, 3.2, 3.5, 3.6, 3, 3.4, 3.5, 2.3, 3.2, 3.5, 3.8, 3, 3.8, 3.2, 3.7, 3.3, 3.2, 3.2, 3.1, 2.3, 2.8, 2.8, 3.3, 2.4, 2.9, 2.7, 2, 3, 2.2, 2.9, 2.9, 3.1, 3, 2.7, 2.2, 2.5, 3.2, 2.8, 2.5, 2.8, 2.9, 3, 2.8, 3, 2.9, 2.6, 2.4, 2.4, 2.7, 2.7, 3, 3.4, 3.1, 2.3, 3, 2.5, 2.6, 3, 2.6, 2.3, 2.7, 3, 2.9, 2.9, 2.5, 2.8, 3.3, 2.7, 3, 2.9, 3, 3, 2.5, 2.9, 2.5, 3.6, 3.2, 2.7, 3, 2.5, 2.8, 3.2, 3, 3.8, 2.6, 2.2, 3.2, 2.8, 2.8, 2.7, 3.3, 3.2, 2.8, 3, 2.8, 3, 2.8, 3.8, 2.8, 2.8, 2.6, 3, 3.4, 3.1, 3, 3.1, 3.1, 3.1, 2.7, 3.2, 3.3, 3, 2.5, 3, 3.4, 3), Petal.Length = c(1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.6, 1.4, 1.1, 1.2, 1.5, 1.3, 1.4, 1.7, 1.5, 1.7, 1.5, 1, 1.7, 1.9, 1.6, 1.6, 1.5, 1.4, 1.6, 1.6, 1.5, 1.5, 1.4, 1.5, 1.2, 1.3, 1.4, 1.3, 1.5, 1.3, 1.3, 1.3, 1.6, 1.9, 1.4, 1.6, 1.4, 1.5, 1.4, 4.7, 4.5, 4.9, 4, 4.6, 4.5, 4.7, 3.3, 4.6, 3.9, 3.5, 4.2, 4, 4.7, 3.6, 4.4, 4.5, 4.1, 4.5, 3.9, 4.8, 4, 4.9, 4.7, 4.3, 4.4, 4.8, 5, 4.5, 3.5, 3.8, 3.7, 3.9, 5.1, 4.5, 4.5, 4.7, 4.4, 4.1, 4, 4.4, 4.6, 4, 3.3, 4.2, 4.2, 4.2, 4.3, 3, 4.1, 6, 5.1, 5.9, 5.6, 5.8, 6.6, 4.5, 6.3, 5.8, 6.1, 5.1, 5.3, 5.5, 5, 5.1, 5.3, 5.5, 6.7, 6.9, 5, 5.7, 4.9, 6.7, 4.9, 5.7, 6, 4.8, 4.9, 5.6, 5.8, 6.1, 6.4, 5.6, 5.1, 5.6, 6.1, 5.6, 5.5, 4.8, 5.4, 5.6, 5.1, 5.1, 5.9, 5.7, 5.2, 5, 5.2, 5.4, 5.1), Petal.Width = c(0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.2, 0.1, 0.1, 0.2, 0.4, 0.4, 0.3, 0.3, 0.3, 0.2, 0.4, 0.2, 0.5, 0.2, 0.2, 0.4, 0.2, 0.2, 0.2, 0.2, 0.4, 0.1, 0.2, 0.2, 0.2, 0.2, 0.1, 0.2, 0.2, 0.3, 0.3, 0.2, 0.6, 0.4, 0.3, 0.2, 0.2, 0.2, 0.2, 1.4, 1.5, 1.5, 1.3, 1.5, 1.3, 1.6, 1, 1.3, 1.4, 1, 1.5, 1, 1.4, 1.3, 1.4, 1.5, 1, 1.5, 1.1, 1.8, 1.3, 1.5, 1.2, 1.3, 1.4, 1.4, 1.7, 1.5, 1, 1.1, 1, 1.2, 1.6, 1.5, 1.6, 1.5, 1.3, 1.3, 1.3, 1.2, 1.4, 1.2, 1, 1.3, 1.2, 1.3, 1.3, 1.1, 1.3, 2.5, 1.9, 2.1, 1.8, 2.2, 2.1, 1.7, 1.8, 1.8, 2.5, 2, 1.9, 2.1, 2, 2.4, 2.3, 1.8, 2.2, 2.3, 1.5, 2.3, 2, 2, 1.8, 2.1, 1.8, 1.8, 1.8, 2.1, 1.6, 1.9, 2, 2.2, 1.5, 1.4, 2.3, 2.4, 1.8, 1.8, 2.1, 2.4, 2.3, 1.9, 2.3, 2.5, 2.3, 1.9, 2, 2.3, 1.8), Species = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c('setosa', 'versicolor', 'virginica'), class = 'factor')), .Names = c('Sepal.Length', 'Sepal.Width', 'Petal.Length', 'Petal.Width', 'Species'), row.names = c(NA, -150L), class = 'data.frame')), .Names = 'object');" + - "do.call('summary', argv)"); + assertEval("argv <- structure(list(object = structure(list(Sepal.Length = c(5.1, 4.9, 4.7, 4.6, 5, 5.4, 4.6, 5, 4.4, 4.9, 5.4, 4.8, 4.8, 4.3, 5.8, 5.7, 5.4, 5.1, 5.7, 5.1, 5.4, 5.1, 4.6, 5.1, 4.8, 5, 5, 5.2, 5.2, 4.7, 4.8, 5.4, 5.2, 5.5, 4.9, 5, 5.5, 4.9, 4.4, 5.1, 5, 4.5, 4.4, 5, 5.1, 4.8, 5.1, 4.6, 5.3, 5, 7, 6.4, 6.9, 5.5, 6.5, 5.7, 6.3, 4.9, 6.6, 5.2, 5, 5.9, 6, 6.1, 5.6, 6.7, 5.6, 5.8, 6.2, 5.6, 5.9, 6.1, 6.3, 6.1, 6.4, 6.6, 6.8, 6.7, 6, 5.7, 5.5, 5.5, 5.8, 6, 5.4, 6, 6.7, 6.3, 5.6, 5.5, 5.5, 6.1, 5.8, 5, 5.6, 5.7, 5.7, 6.2, 5.1, 5.7, 6.3, 5.8, 7.1, 6.3, 6.5, 7.6, 4.9, 7.3, 6.7, 7.2, 6.5, 6.4, 6.8, 5.7, 5.8, 6.4, 6.5, 7.7, 7.7, 6, 6.9, 5.6, 7.7, 6.3, 6.7, 7.2, 6.2, 6.1, 6.4, 7.2, 7.4, 7.9, 6.4, 6.3, 6.1, 7.7, 6.3, 6.4, 6, 6.9, 6.7, 6.9, 5.8, 6.8, 6.7, 6.7, 6.3, 6.5, 6.2, 5.9), Sepal.Width = c(3.5, 3, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.4, 3, 3, 4, 4.4, 3.9, 3.5, 3.8, 3.8, 3.4, 3.7, 3.6, 3.3, 3.4, 3, 3.4, 3.5, 3.4, 3.2, 3.1, 3.4, 4.1, 4.2, 3.1, 3.2, 3.5, 3.6, 3, 3.4, 3.5, 2.3, 3.2, 3.5, 3.8, 3, 3.8, 3.2, 3.7, 3.3, 3.2, 3.2, 3.1, 2.3, 2.8, 2.8, 3.3, 2.4, 2.9, 2.7, 2, 3, 2.2, 2.9, 2.9, 3.1, 3, 2.7, 2.2, 2.5, 3.2, 2.8, 2.5, 2.8, 2.9, 3, 2.8, 3, 2.9, 2.6, 2.4, 2.4, 2.7, 2.7, 3, 3.4, 3.1, 2.3, 3, 2.5, 2.6, 3, 2.6, 2.3, 2.7, 3, 2.9, 2.9, 2.5, 2.8, 3.3, 2.7, 3, 2.9, 3, 3, 2.5, 2.9, 2.5, 3.6, 3.2, 2.7, 3, 2.5, 2.8, 3.2, 3, 3.8, 2.6, 2.2, 3.2, 2.8, 2.8, 2.7, 3.3, 3.2, 2.8, 3, 2.8, 3, 2.8, 3.8, 2.8, 2.8, 2.6, 3, 3.4, 3.1, 3, 3.1, 3.1, 3.1, 2.7, 3.2, 3.3, 3, 2.5, 3, 3.4, 3), Petal.Length = c(1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.6, 1.4, 1.1, 1.2, 1.5, 1.3, 1.4, 1.7, 1.5, 1.7, 1.5, 1, 1.7, 1.9, 1.6, 1.6, 1.5, 1.4, 1.6, 1.6, 1.5, 1.5, 1.4, 1.5, 1.2, 1.3, 1.4, 1.3, 1.5, 1.3, 1.3, 1.3, 1.6, 1.9, 1.4, 1.6, 1.4, 1.5, 1.4, 4.7, 4.5, 4.9, 4, 4.6, 4.5, 4.7, 3.3, 4.6, 3.9, 3.5, 4.2, 4, 4.7, 3.6, 4.4, 4.5, 4.1, 4.5, 3.9, 4.8, 4, 4.9, 4.7, 4.3, 4.4, 4.8, 5, 4.5, 3.5, 3.8, 3.7, 3.9, 5.1, 4.5, 4.5, 4.7, 4.4, 4.1, 4, 4.4, 4.6, 4, 3.3, 4.2, 4.2, 4.2, 4.3, 3, 4.1, 6, 5.1, 5.9, 5.6, 5.8, 6.6, 4.5, 6.3, 5.8, 6.1, 5.1, 5.3, 5.5, 5, 5.1, 5.3, 5.5, 6.7, 6.9, 5, 5.7, 4.9, 6.7, 4.9, 5.7, 6, 4.8, 4.9, 5.6, 5.8, 6.1, 6.4, 5.6, 5.1, 5.6, 6.1, 5.6, 5.5, 4.8, 5.4, 5.6, 5.1, 5.1, 5.9, 5.7, 5.2, 5, 5.2, 5.4, 5.1), Petal.Width = c(0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.2, 0.1, 0.1, 0.2, 0.4, 0.4, 0.3, 0.3, 0.3, 0.2, 0.4, 0.2, 0.5, 0.2, 0.2, 0.4, 0.2, 0.2, 0.2, 0.2, 0.4, 0.1, 0.2, 0.2, 0.2, 0.2, 0.1, 0.2, 0.2, 0.3, 0.3, 0.2, 0.6, 0.4, 0.3, 0.2, 0.2, 0.2, 0.2, 1.4, 1.5, 1.5, 1.3, 1.5, 1.3, 1.6, 1, 1.3, 1.4, 1, 1.5, 1, 1.4, 1.3, 1.4, 1.5, 1, 1.5, 1.1, 1.8, 1.3, 1.5, 1.2, 1.3, 1.4, 1.4, 1.7, 1.5, 1, 1.1, 1, 1.2, 1.6, 1.5, 1.6, 1.5, 1.3, 1.3, 1.3, 1.2, 1.4, 1.2, 1, 1.3, 1.2, 1.3, 1.3, 1.1, 1.3, 2.5, 1.9, 2.1, 1.8, 2.2, 2.1, 1.7, 1.8, 1.8, 2.5, 2, 1.9, 2.1, 2, 2.4, 2.3, 1.8, 2.2, 2.3, 1.5, 2.3, 2, 2, 1.8, 2.1, 1.8, 1.8, 1.8, 2.1, 1.6, 1.9, 2, 2.2, 1.5, 1.4, 2.3, 2.4, 1.8, 1.8, 2.1, 2.4, 2.3, 1.9, 2.3, 2.5, 2.3, 1.9, 2, 2.3, 1.8), Species = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c('setosa', 'versicolor', 'virginica'), class = 'factor')), .Names = c('Sepal.Length', 'Sepal.Width', 'Petal.Length', 'Petal.Width', 'Species'), row.names = c(NA, -150L), class = 'data.frame')), .Names = 'object');" + + "do.call('summary', argv)"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_switch.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_switch.java index ba05e9011ec621e2bcbce46e362bede08c2b71cb..823c928e5a0ef05c74cdd9e18ff79237265b29bd 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_switch.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_switch.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -50,4 +50,14 @@ public class TestBuiltin_switch extends TestBase { assertEval(Output.IgnoreErrorContext, "{ x <- \"!\"; v <- switch(x, v77, \"<=\" =, \"<\" =, \">\" = 99, v55)}"); assertEval("{ x <- \"!\"; v <- switch(x, \"\"=v77, \"<=\" =, \"<\" =, \">\" = 99, v55)}"); } + + @Test + public void testSwitchInvalidExpr() { + assertEval("{ x <- switch(NA, 1, 2, 3); x }"); + assertEval("{ switch(quote(a), 1, 2, 3) }"); + assertEval("{ x <- switch(expression(quote(1)), 1, 2, 3); x }"); + assertEval("{ x <- switch(expression(quote(1), quote(2)), 1, 2, 3); x }"); + assertEval("{ x <- switch(list(2), 1, 2, 3); x }"); + assertEval("{ x <- switch(list(1,2,3), 1, 2, 3); x }"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tdefault.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tdefault.java index 58b7bf9977d3a3335d234442028cb08902a32198..6773ef1d1aa7659430e9f11b781b27a290b2bf0a 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tdefault.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tdefault.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. */ @@ -79,7 +79,7 @@ public class TestBuiltin_tdefault extends TestBase { @Test public void testtdefault13() { - assertEval(Ignored.Unknown, "argv <- list(structure(c(0, 0, 0, 0, 0, 0, 3.95252516672997e-323, 0, 0, 0, 0, 0), .Dim = c(12L, 1L))); .Internal(t.default(argv[[1]]))"); + assertEval("argv <- list(structure(c(0, 0, 0, 0, 0, 0, 3.95252516672997e-323, 0, 0, 0, 0, 0), .Dim = c(12L, 1L))); .Internal(t.default(argv[[1]]))"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tracemem.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tracemem.java index 7b4e4e6f413c56d80610c894335b45f40983ee96..dbe3342863f881651ba34935f497ef4e56f6405e 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tracemem.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tracemem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -54,5 +54,6 @@ public class TestBuiltin_tracemem extends TestBase { // intended semantics of retracemem is not clear, this tests what is definitely intended: // retracemem starts tracing of its first argument assertEval(Output.ContainsReferences, "v <- c(1,10,100); tracemem(v); x <- v[-1]; retracemem(x, retracemem(v)); u <- x; u[[1]] <- 42;"); + assertEval(Output.ContainsReferences, "x<-1:10; retracemem(x, c(\"first\", \"second\")) "); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unlist.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unlist.java index 3bf186353d4719108594bd729427de2d3cd441cc..7508bec871d30bf9a0cc7024e238c45af050a967 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unlist.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unlist.java @@ -117,7 +117,7 @@ public class TestBuiltin_unlist extends TestBase { @Test public void testunlist20() { - assertEval(Ignored.Unknown, "argv <- list(structure(list(`1` = 2.47032822920623e-323), .Names = '1'), FALSE, TRUE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]]))"); + assertEval("argv <- list(structure(list(`1` = 2.47032822920623e-323), .Names = '1'), FALSE, TRUE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]]))"); } @Test @@ -152,8 +152,8 @@ public class TestBuiltin_unlist extends TestBase { @Test public void testunlist27() { - assertEval(Ignored.Unknown, - "argv <- list(list(structure(list(structure(c(0.398105880367068, -0.612026393250771, 0.341119691424425, -1.12936309608079, 1.43302370170104, 1.98039989850586, -0.367221476466509, -1.04413462631653, 0.569719627442413, -0.135054603880824, 2.40161776050478, -0.0392400027331692, 0.689739362450777, 0.0280021587806661, -0.743273208882405, 0.188792299514343, -1.80495862889104, 1.46555486156289, 0.153253338211898, 2.17261167036215, 0.475509528899663, -0.709946430921815, 0.610726353489055, -0.934097631644252, -1.2536334002391, 0.291446235517463, -0.443291873218433, 0.00110535163162413, 0.0743413241516641, -0.589520946188072, -0.568668732818502, -0.135178615123832, 1.1780869965732, -1.52356680042976, 0.593946187628422, 0.332950371213518, 1.06309983727636, -0.304183923634301, 0.370018809916288, 0.267098790772231, -0.54252003099165, 1.20786780598317, 1.16040261569495, 0.700213649514998, 1.58683345454085, 0.558486425565304, -1.27659220845804, -0.573265414236886, -1.22461261489836, -0.473400636439312, -0.620366677224124, 0.0421158731442352, -0.910921648552446, 0.158028772404075, -0.654584643918818, 1.76728726937265, 0.716707476017206, 0.910174229495227, 0.384185357826345, 1.68217608051942, -0.635736453948977, -0.461644730360566, 1.43228223854166, -0.650696353310367, -0.207380743601965, -0.392807929441984, -0.319992868548507, -0.279113302976559, 0.494188331267827, -0.177330482269606, -0.505957462114257, 1.34303882517041, -0.214579408546869, -0.179556530043387, -0.100190741213562, 0.712666307051405, -0.0735644041263263, -0.0376341714670479, -0.681660478755657, -0.324270272246319, 0.0601604404345152, -0.588894486259664, 0.531496192632572, -1.51839408178679, 0.306557860789766, -1.53644982353759, -0.300976126836611, -0.528279904445006, -0.652094780680999, -0.0568967778473925, -1.91435942568001, 1.17658331201856, -1.664972436212, -0.463530401472386, -1.11592010504285, -0.750819001193448, 2.08716654562835, 0.0173956196932517, -1.28630053043433, -1.64060553441858), .Label = structure(list(c(-1.91442143130152, -0.573203408615382), c(-0.934159637265755, -0.300914121215107), c(-0.568730738440006, 0.0174576253147555), c(-0.279175308598063, 0.384247363447848), c(0.0279401531591622, 1.16046462131646), c(0.398043874745564, 2.40167976612628)), class = 'shingleLevel'), class = 'shingle')), row.names = c(NA, -100L), class = 'data.frame'), structure(list(c(0.450187101272656, -0.018559832714638, -0.318068374543844, -0.929362147453702, -1.48746031014148, -1.07519229661568, 1.00002880371391, -0.621266694796823, -1.38442684738449, 1.86929062242358, 0.425100377372448, -0.238647100913033, 1.05848304870902, 0.886422651374936, -0.619243048231147, 2.20610246454047, -0.255027030141015, -1.42449465021281, -0.144399601954219, 0.207538339232345, 2.30797839905936, 0.105802367893711, 0.456998805423414, -0.077152935356531, -0.334000842366544, -0.0347260283112762, 0.787639605630162, 2.07524500865228, 1.02739243876377, 1.2079083983867, -1.23132342155804, 0.983895570053379, 0.219924803660651, -1.46725002909224, 0.521022742648139, -0.158754604716016, 1.4645873119698, -0.766081999604665, -0.430211753928547, -0.926109497377437, -0.17710396143654, 0.402011779486338, -0.731748173119606, 0.830373167981674, -1.20808278630446, -1.04798441280774, 1.44115770684428, -1.01584746530465, 0.411974712317515, -0.38107605110892, 0.409401839650934, 1.68887328620405, 1.58658843344197, -0.330907800682766, -2.28523553529247, 2.49766158983416, 0.667066166765493, 0.5413273359637, -0.0133995231459087, 0.510108422952926, -0.164375831769667, 0.420694643254513, -0.400246743977644, -1.37020787754746, 0.987838267454879, 1.51974502549955, -0.308740569225614, -1.25328975560769, 0.642241305677824, -0.0447091368939791, -1.73321840682484, 0.00213185968026965, -0.630300333928146, -0.340968579860405, -1.15657236263585, 1.80314190791747, -0.331132036391221, -1.60551341225308, 0.197193438739481, 0.263175646405474, -0.985826700409291, -2.88892067167955, -0.640481702565115, 0.570507635920485, -0.05972327604261, -0.0981787440052344, 0.560820728620116, -1.18645863857947, 1.09677704427424, -0.00534402827816569, 0.707310667398079, 1.03410773473746, 0.223480414915304, -0.878707612866019, 1.16296455596733, -2.00016494478548, -0.544790740001725, -0.255670709156989, -0.166121036765006, 1.02046390878411)), row.names = c(NA, -100L), class = 'data.frame')), FALSE, FALSE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]]))"); + assertEval(Output.IgnoreWhitespace, + "argv <- list(list(structure(list(structure(c(0.398105880367068, -0.612026393250771, 0.341119691424425, -1.12936309608079, 1.43302370170104, 1.98039989850586, -0.367221476466509, -1.04413462631653, 0.569719627442413, -0.135054603880824, 2.40161776050478, -0.0392400027331692, 0.689739362450777, 0.0280021587806661, -0.743273208882405, 0.188792299514343, -1.80495862889104, 1.46555486156289, 0.153253338211898, 2.17261167036215, 0.475509528899663, -0.709946430921815, 0.610726353489055, -0.934097631644252, -1.2536334002391, 0.291446235517463, -0.443291873218433, 0.00110535163162413, 0.0743413241516641, -0.589520946188072, -0.568668732818502, -0.135178615123832, 1.1780869965732, -1.52356680042976, 0.593946187628422, 0.332950371213518, 1.06309983727636, -0.304183923634301, 0.370018809916288, 0.267098790772231, -0.54252003099165, 1.20786780598317, 1.16040261569495, 0.700213649514998, 1.58683345454085, 0.558486425565304, -1.27659220845804, -0.573265414236886, -1.22461261489836, -0.473400636439312, -0.620366677224124, 0.0421158731442352, -0.910921648552446, 0.158028772404075, -0.654584643918818, 1.76728726937265, 0.716707476017206, 0.910174229495227, 0.384185357826345, 1.68217608051942, -0.635736453948977, -0.461644730360566, 1.43228223854166, -0.650696353310367, -0.207380743601965, -0.392807929441984, -0.319992868548507, -0.279113302976559, 0.494188331267827, -0.177330482269606, -0.505957462114257, 1.34303882517041, -0.214579408546869, -0.179556530043387, -0.100190741213562, 0.712666307051405, -0.0735644041263263, -0.0376341714670479, -0.681660478755657, -0.324270272246319, 0.0601604404345152, -0.588894486259664, 0.531496192632572, -1.51839408178679, 0.306557860789766, -1.53644982353759, -0.300976126836611, -0.528279904445006, -0.652094780680999, -0.0568967778473925, -1.91435942568001, 1.17658331201856, -1.664972436212, -0.463530401472386, -1.11592010504285, -0.750819001193448, 2.08716654562835, 0.0173956196932517, -1.28630053043433, -1.64060553441858), .Label = structure(list(c(-1.91442143130152, -0.573203408615382), c(-0.934159637265755, -0.300914121215107), c(-0.568730738440006, 0.0174576253147555), c(-0.279175308598063, 0.384247363447848), c(0.0279401531591622, 1.16046462131646), c(0.398043874745564, 2.40167976612628)), class = 'shingleLevel'), class = 'shingle')), row.names = c(NA, -100L), class = 'data.frame'), structure(list(c(0.450187101272656, -0.018559832714638, -0.318068374543844, -0.929362147453702, -1.48746031014148, -1.07519229661568, 1.00002880371391, -0.621266694796823, -1.38442684738449, 1.86929062242358, 0.425100377372448, -0.238647100913033, 1.05848304870902, 0.886422651374936, -0.619243048231147, 2.20610246454047, -0.255027030141015, -1.42449465021281, -0.144399601954219, 0.207538339232345, 2.30797839905936, 0.105802367893711, 0.456998805423414, -0.077152935356531, -0.334000842366544, -0.0347260283112762, 0.787639605630162, 2.07524500865228, 1.02739243876377, 1.2079083983867, -1.23132342155804, 0.983895570053379, 0.219924803660651, -1.46725002909224, 0.521022742648139, -0.158754604716016, 1.4645873119698, -0.766081999604665, -0.430211753928547, -0.926109497377437, -0.17710396143654, 0.402011779486338, -0.731748173119606, 0.830373167981674, -1.20808278630446, -1.04798441280774, 1.44115770684428, -1.01584746530465, 0.411974712317515, -0.38107605110892, 0.409401839650934, 1.68887328620405, 1.58658843344197, -0.330907800682766, -2.28523553529247, 2.49766158983416, 0.667066166765493, 0.5413273359637, -0.0133995231459087, 0.510108422952926, -0.164375831769667, 0.420694643254513, -0.400246743977644, -1.37020787754746, 0.987838267454879, 1.51974502549955, -0.308740569225614, -1.25328975560769, 0.642241305677824, -0.0447091368939791, -1.73321840682484, 0.00213185968026965, -0.630300333928146, -0.340968579860405, -1.15657236263585, 1.80314190791747, -0.331132036391221, -1.60551341225308, 0.197193438739481, 0.263175646405474)), row.names = c(NA, -80L), class = 'data.frame')), FALSE, FALSE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]]))"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unserialize.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unserialize.java index 786a26fcd95d42e49bde626fbff43eb454c63004..db3283245f27635d8ca949d6a756141a740bee62 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unserialize.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unserialize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -29,8 +29,8 @@ import com.oracle.truffle.r.test.TestBase; public class TestBuiltin_unserialize extends TestBase { private static final String[] BASIC_TYPE_VALUES = new String[]{ - "c(1,2,3,4)", "3L", "42", "\"Hello world\"", "3+2i", "TRUE", "head(mtcars)", - "data.frame(col1=c(9,8,7), col2=1:3)", "expression(x+1)", "list(1,2)", "NULL" + "c(1,2,3,4)", "3L", "c(1L,2L,99L,NA)", "1:15", "(1:15)+0.1", "42", "\"Hello world\"", "3+2i", "c(3+2i, 5+944i, NA)", "TRUE", "c(TRUE, FALSE, NA, FALSE, TRUE)", + "head(mtcars)", "data.frame(col1=c(9,8,7), col2=1:3)", "expression(x+1)", "list(1,2)", "NULL" }; @Test @@ -88,7 +88,7 @@ public class TestBuiltin_unserialize extends TestBase { assertEval(Output.IgnoreWhitespace, "options(keep.source=FALSE); unserialize(serialize(quote(function(x,y,...) { 1 }), connection=NULL))"); assertEval(Output.IgnoreWhitespace, "options(keep.source=FALSE); unserialize(serialize(quote(function(x,y=1,...) { NA }), connection=NULL))"); assertEval("options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y,...) { NA }), connection=NULL))"); - assertEval(Ignored.OutputFormatting, "options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y,...) { !!NA }), connection=NULL))"); + assertEval("options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y,...) { !!NA }), connection=NULL))"); assertEval("options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y,...) { !1+5i }), connection=NULL))"); assertEval("options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y=c(1,2,3),z=\"foo\",...) { !1+5i }), connection=NULL))"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vapply.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vapply.java index 3bbd8e7428859b0f9b4392ef7f3621d937337ba8..931015c40709bdd2df477a7f1e4382553d67ffda 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vapply.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vapply.java @@ -42,6 +42,10 @@ public class TestBuiltin_vapply extends TestBase { assertEval(Output.IgnoreErrorContext, "{ vapply(c(\"foo\", \"bar\"), function(x) FALSE, c(TRUE), USE.NAMES=logical()) }"); assertEval(Output.IgnoreErrorContext, "{ vapply(c(\"foo\", \"bar\"), function(x) FALSE, c(TRUE), USE.NAMES=\"42\") }"); assertEval("{ vapply(c(\"foo\", \"bar\"), function(x) FALSE, c(TRUE), USE.NAMES=42) }"); + + assertEval("{ vapply(quote(a), function(x) 42, 1); }"); + assertEval(Output.IgnoreErrorContext, "{ vapply(quote(a), function(x) quote(b), quote(a)); }"); + assertEval("{ vapply(c(1,2,3), 42, 1); }"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_writeChar.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_writeChar.java new file mode 100644 index 0000000000000000000000000000000000000000..3f3cde5a1770d791f68dc31b149606377777ac55 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_writeChar.java @@ -0,0 +1,38 @@ +/* + * 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.builtins; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +// Checkstyle: stop line length check + +public class TestBuiltin_writeChar extends TestBase { + @Test + public void testwriteCharArgumentsValidation() { + assertEval("writeChar(NULL, 1)"); + assertEval("writeChar(list(), 1)"); + assertEval("writeChar(42, 1)"); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/fifo_GnuR_example.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/fifo_GnuR_example.R new file mode 100644 index 0000000000000000000000000000000000000000..9ffda2392b2cf9143bc149bb054bcbdf1e8a3878 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/fifo_GnuR_example.R @@ -0,0 +1,9 @@ +# Ignored +# This test does currently not work on Java because there is simply no way in Java for opening a UNIX named pipe non-blocking. +if(capabilities("fifo")) { + zz <- fifo("foo-fifo", "w+") + writeLines("abc", zz) + print(readLines(zz)) + close(zz) + unlink("foo-fifo") +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readBin.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readBin.R new file mode 100644 index 0000000000000000000000000000000000000000..cbcaa996728f82358602d6826d80df24ecc80578 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readBin.R @@ -0,0 +1,21 @@ +zz <- rawConnection(raw(0), "wb") +writeBin(1:10, zz) +writeBin(pi, zz) +writeBin(pi, zz) +writeBin(pi^2, zz) +writeBin(pi+3i, zz) +writeBin("A test of a connection", zz) +z <- paste("A very long string", 1:100, collapse = " + ") +writeBin(z, zz) +res <- rawConnectionValue(zz) +close(zz) + +zz <- rawConnection(res, "rb") +readBin(zz, integer()) +readBin(zz, integer()) +readBin(zz, numeric()) +readBin(zz, complex()) +readBin(zz, character()) +z2 <- readBin(zz, character()) +close(zz) +z2 \ No newline at end of file diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readWriteBin.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readWriteBin.R new file mode 100644 index 0000000000000000000000000000000000000000..3731f5f2196ee96a1d7c7ff44541fe1ecbaf6d7b --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readWriteBin.R @@ -0,0 +1,12 @@ +## signed vs unsigned ints +len <- 100000 +zz <- rawConnection(raw(0), "wb") +x <- as.raw((1:len) %% 255) +writeBin(x, zz) +res <- rawConnectionValue(zz) +close(zz) + +zz <- rawConnection(res, "rb") +res1 <- readBin(zz, "raw", len) +close(zz) +Reduce(`&&`, res == res1, TRUE) \ No newline at end of file diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_seek.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_seek.R new file mode 100644 index 0000000000000000000000000000000000000000..2d2fd0d1036ebdac1987164832c3ac621abd3c17 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_seek.R @@ -0,0 +1,8 @@ +zz <- rawConnection(raw(0), "r+b") +writeBin(LETTERS, zz) +seek(zz, 0) +readChar(zz, 1) +seek(zz, 0) +writeBin(letters[1:3], zz) +rawConnectionValue(zz) +close(zz) diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_writeBin.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_writeBin.R new file mode 100644 index 0000000000000000000000000000000000000000..62ad8c98d419c4cd661f88eaa869e0d6cc460872 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_writeBin.R @@ -0,0 +1,16 @@ +zz <- rawConnection(raw(0), "wb") +writeBin(1:10, zz) +writeBin(pi, zz, endian = "swap") +writeBin(pi, zz, size = 4) +writeBin(pi^2, zz, size = 4, endian = "swap") +writeBin(pi+3i, zz) +writeBin("A test of a connection", zz) +z <- paste("A very long string", 1:100, collapse = " + ") +writeBin(z, zz) +if(.Machine$sizeof.long == 8 || .Machine$sizeof.longlong == 8) + writeBin(as.integer(5^(1:10)), zz, size = 8) +if((s <- .Machine$sizeof.longdouble) > 8) + writeBin((pi/3)^(1:10), zz, size = s) +res <- rawConnectionValue(zz) +close(zz) +res \ No newline at end of file diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R new file mode 100644 index 0000000000000000000000000000000000000000..4c6ed7c53290a25b6b54c7ed191e8b416e5c466d --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R @@ -0,0 +1,12 @@ +cat("TITLE extra line", "2 3 5 7", "", "11 13 17", file = "ex.data", sep = "\n") +r0 <- readLines("ex.data", n = -1) +unlink("ex.data") +cat("123\nabc", file = "test1") +r1 <- readLines("test1") +con <- file("test1", "r", blocking = FALSE) +r2 <- readLines(con) +cat(" def\n", file = "test1", append = TRUE) +r3 <- readLines(con) +close(con) +unlink("test1") +print(c(r0, r1, r2, r3)) \ No newline at end of file diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/textConnection.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/textConnection.R new file mode 100644 index 0000000000000000000000000000000000000000..7785051d50e512c1053436f50003e228a7d7fb66 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/textConnection.R @@ -0,0 +1,30 @@ +zz <- textConnection(LETTERS) +readLines(zz, 2) +scan(zz, "", 4) +pushBack(c("aa", "bb"), zz) +scan(zz, "", 4) +close(zz) + +zz <- textConnection("foo", "w") +writeLines(c("testit1", "testit2"), zz) +cat("testit3 ", file = zz) +isIncomplete(zz) +cat("testit4\n", file = zz) +# removed this call since we haven't implemented it yet +# isIncomplete(zz) +close(zz) +foo + +# capture R output: use part of example from help(lm) +zz <- textConnection("foo", "w") +ctl <- c(4.17, 5.58, 5.18, 6.11, 4.5, 4.61, 5.17, 4.53, 5.33, 5.14) +trt <- c(4.81, 4.17, 4.41, 3.59, 5.87, 3.83, 6.03, 4.89, 4.32, 4.69) +group <- gl(2, 10, 20, labels = c("Ctl", "Trt")) +weight <- c(ctl, trt) +sink(zz) +anova(lm.D9 <- lm(weight ~ group)) +cat("\nSummary of Residuals:\n\n") +summary(resid(lm.D9)) +sink() +close(zz) +cat(foo, sep = "\n") \ No newline at end of file diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing1.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing1.R new file mode 100644 index 0000000000000000000000000000000000000000..5a96c5964206e95944672aad6f548b19288dc56f --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing1.R @@ -0,0 +1,14 @@ +# test remote update in global space - values should remain distinct + +if (length(grep("FastR", R.Version()$version.string)) == 1) { + ch1 <- .fastr.channel.create(1L) + code <- "ch2 <- .fastr.channel.get(1L); x <- 7; .fastr.channel.send(ch2, x)" + x <- 42 + cx <- .fastr.context.spawn(code) + y <- .fastr.channel.receive(ch1) + .fastr.context.join(cx) + .fastr.channel.close(ch1) + print(c(x, y)) +} else { + print(c(42L, 7L)) +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing2.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing2.R new file mode 100644 index 0000000000000000000000000000000000000000..3c02fba5abc04a0d0c663d5c715828f69efde269 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing2.R @@ -0,0 +1,18 @@ +# test subsequent remote updates in global space - second time value should have been reset + +if (length(grep("FastR", R.Version()$version.string)) == 1) { + ch1 <- .fastr.channel.create(1L) + code <- "ch2 <- .fastr.channel.get(1L); x <- 7; .fastr.channel.send(ch2, x)" + x <- 42 + cx <- .fastr.context.spawn(code) + y <- .fastr.channel.receive(ch1) + .fastr.context.join(cx) + code <- "ch2 <- .fastr.channel.get(1L); res <- tryCatch(z <- x, error=function(e) e); .fastr.channel.send(ch2, res[[1]])" + cx <- .fastr.context.spawn(code) + y <- .fastr.channel.receive(ch1) + .fastr.context.join(cx) + .fastr.channel.close(ch1) + print(y) +} else { + print("object 'x' not found") +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing3.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing3.R new file mode 100644 index 0000000000000000000000000000000000000000..ec10067a70355cc808f00d8dbb2eec40c0b4633e --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing3.R @@ -0,0 +1,15 @@ +# test remote update in base space - values should remain distinct + +if (length(grep("FastR", R.Version()$version.string)) == 1) { + ch1 <- .fastr.channel.create(1L) + # use an obscure name so it doesn't clash with other tests + code <- "ch2 <- .fastr.channel.get(1L); assign('tmp59857', 7, env=baseenv()); .fastr.channel.send(ch2, get('tmp59857', env=baseenv(), inherits=F))" + assign('tmp59857', 42, env=baseenv()) + cx <- .fastr.context.spawn(code) + y <- .fastr.channel.receive(ch1) + .fastr.context.join(cx) + .fastr.channel.close(ch1) + print(c(get('tmp59857', env=baseenv(), inherits=F), y)) +} else { + print(c(42L, 7L)) +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing4.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing4.R new file mode 100644 index 0000000000000000000000000000000000000000..147da5fcf5939daa2e22f3a78696a799cbd6795a --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing4.R @@ -0,0 +1,23 @@ +# test access to global environment with multiple context instantiations varying context number + +if (length(grep("FastR", R.Version()$version.string)) == 1) { + ch1 <- .fastr.channel.create(1L) + code <- "ch2 <- .fastr.channel.get(1L); x <- .fastr.channel.receive(ch2); .fastr.channel.send(ch2, x)" + x <- 7 + # create one child context + cx <- .fastr.context.spawn(code) + .fastr.channel.send(ch1, 7) + y <- .fastr.channel.receive(ch1) + .fastr.context.join(cx) + # create two child contexts + cx <- .fastr.context.spawn(rep(code, 2)) + .fastr.channel.send(ch1, 42) + .fastr.channel.send(ch1, 24) + y <- .fastr.channel.receive(ch1) + z <- .fastr.channel.receive(ch1) + + .fastr.channel.close(ch1) + print(sort(c(y, z))) +} else { + print(c(24L, 42L)) +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RListMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RListMRTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a1af763c7576321ec53e89030ecfa14f34125a5b --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RListMRTest.java @@ -0,0 +1,100 @@ +/* + * 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.KeyInfo; +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 org.junit.Test; + +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; + +public class RListMRTest { + + @Test + public void testKeysReadWrite() throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException { + TruffleObject l = createRListTruffleObject("n1=1L, n2=2L, 3, 4"); + + TruffleObject keys = ForeignAccess.sendKeys(Message.KEYS.createNode(), l); + assertEquals("n1", ForeignAccess.sendRead(Message.READ.createNode(), keys, 0)); + assertEquals("n2", ForeignAccess.sendRead(Message.READ.createNode(), keys, 1)); + assertEquals("", ForeignAccess.sendRead(Message.READ.createNode(), keys, 2)); + assertEquals("", ForeignAccess.sendRead(Message.READ.createNode(), keys, 3)); + + assertEquals(4, ForeignAccess.sendGetSize(Message.GET_SIZE.createNode(), keys)); + assertEquals(1, ForeignAccess.sendRead(Message.READ.createNode(), l, "n1")); + assertEquals(2, ForeignAccess.sendRead(Message.READ.createNode(), l, "n2")); + + // TODO fails - should this return NULL as in l[""] or 3 as in l$"" + // ElementAccessMode.FIELD_SUBSCRIPT vs .SUBSCRIPT doesn't seem to have any effect + // assertEquals(3, ForeignAccess.sendRead(Message.READ.createNode(), l, "")); + + // TODO - more tests for NA, ... ? + + l = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), l, "n2", 123); + assertEquals(123, ForeignAccess.sendRead(Message.READ.createNode(), l, "n2")); + } + + @Test + public void testKeysInfo() throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException { + TruffleObject l = createRListTruffleObject("n1=1, n2=2"); + int info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, "nnoonnee"); + assertFalse(KeyInfo.isExisting(info)); + assertFalse(KeyInfo.isReadable(info)); + assertFalse(KeyInfo.isWritable(info)); + assertFalse(KeyInfo.isInvocable(info)); + assertFalse(KeyInfo.isInternal(info)); + + info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, "n2"); + assertTrue(KeyInfo.isExisting(info)); + assertTrue(KeyInfo.isReadable(info)); + assertTrue(KeyInfo.isWritable(info)); + assertFalse(KeyInfo.isInvocable(info)); + assertFalse(KeyInfo.isInternal(info)); + + l = createRListTruffleObject("f=function() {}"); + info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, "f"); + assertTrue(KeyInfo.isExisting(info)); + assertTrue(KeyInfo.isReadable(info)); + assertTrue(KeyInfo.isWritable(info)); + assertTrue(KeyInfo.isInvocable(info)); + assertFalse(KeyInfo.isInternal(info)); + } + + private TruffleObject createRListTruffleObject(String values) { + PolyglotEngine engine = PolyglotEngine.newBuilder().build(); + Source src = Source.newBuilder("list(" + values + ")").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 new file mode 100644 index 0000000000000000000000000000000000000000..e7d55912a9dfb820431d590ee1ffa684acb7c531 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java @@ -0,0 +1,162 @@ +/* + * 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.shell; + +import com.oracle.truffle.api.vm.PolyglotEngine; +import com.oracle.truffle.r.engine.shell.JLineConsoleCompleter; +import com.oracle.truffle.r.runtime.RCmdOptions; +import com.oracle.truffle.r.runtime.context.ConsoleHandler; +import com.oracle.truffle.r.runtime.context.ContextInfo; +import com.oracle.truffle.r.runtime.context.RContext; +import java.io.File; +import org.junit.Test; + +import java.util.LinkedList; +import org.junit.After; +import org.junit.Assert; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import org.junit.Before; + +public class TestJLineConsoleCompleter { + + private PolyglotEngine engine; + private ConsoleHandler consoleHandler; + private JLineConsoleCompleter consoleCompleter; + + @Before + public void before() { + consoleHandler = new DummyConsoleHandler(); + consoleCompleter = new JLineConsoleCompleter(consoleHandler); + JLineConsoleCompleter.testingMode(); + ContextInfo info = ContextInfo.createNoRestore(RCmdOptions.Client.R, null, RContext.ContextKind.SHARE_NOTHING, null, consoleHandler); + engine = info.createVM(PolyglotEngine.newBuilder()); + } + + @After + public void dispose() { + if (engine != null) { + engine.dispose(); + } + } + + @Test + public void testCompl() { + assertCompl("", 0); + assertCompl("", 1); + assertCompl(" ", 1); + + assertCompl("(", 0); + assertCompl("(", 1); + assertCompl("=", 1); + assertCompl("$", 1); + + assertCompl("strt", 4, "strtoi", "strtrim"); + assertCompl("strto", 5, "strtoi"); + assertCompl("strtoi", 5, "strtoi"); + assertCompl("strtoi", 4, "strtoi", "strtrim"); + assertCompl("strto ", 6); + + assertCompl("base::strt", 10, "base::strtoi", "base::strtrim"); + assertCompl("base:::strt", 11, "base:::strtoi", "base:::strtrim"); + assertCompl("base:::strttrt", 14, "base:::"); + + assertCompl("strt(", 4, "strtoi", "strtrim"); + assertCompl("strt(", 5); + assertCompl("f(strt", 6, "strtoi", "strtrim"); + assertCompl("f(base::strt", 12, "base::strtoi", "base::strtrim"); + assertCompl("f(strt(trt", 6, "strtoi", "strtrim"); + assertCompl("f(strt(trt", 10); + assertCompl("f(strt(strto", 11, "strtoi", "strtrim"); + assertCompl("f(strt(strto", 12, "strtoi"); + + String noName = "_f_f_f_"; + assertCompl(noName + ".", 7); + assertCompl(noName + ".", 8); + assertCompl(noName + "." + File.separator, 9); + assertCompl(noName + "'", 7); + assertCompl(noName + "'", 8, NOT_EMPTY); + assertCompl(noName + "'." + File.separator, 8, NOT_EMPTY); + assertCompl(noName + "'." + File.separator, 9, NOT_EMPTY); + assertCompl(noName + "'." + File.separator, 10, NOT_EMPTY); + assertCompl(noName + "\"." + File.separator, 8, NOT_EMPTY); + } + + // e.g. check if the file path completion returned at least something + private static final String NOT_EMPTY = "_@_Only.Check.If.Result.Not.Empty_@_"; + + private void assertCompl(String buffer, int cursor, String... expected) { + LinkedList<CharSequence> l = new LinkedList<>(); + consoleCompleter.complete(buffer, cursor, l); + + if (expected == null || expected.length == 0) { + assertTrue(l.isEmpty()); + } else if (expected.length == 1 && NOT_EMPTY.equals(expected[0])) { + assertFalse(l.isEmpty()); + } else { + Assert.assertArrayEquals(expected, l.toArray(new CharSequence[l.size()])); + } + } + + private class DummyConsoleHandler implements ConsoleHandler { + @Override + public void println(String s) { + } + + @Override + public void print(String s) { + } + + @Override + public void printErrorln(String s) { + } + + @Override + public void printError(String s) { + } + + @Override + public String readLine() { + return ""; + } + + @Override + public boolean isInteractive() { + return false; + } + + @Override + public String getPrompt() { + return ""; + } + + @Override + public void setPrompt(String prompt) { + } + + @Override + public String getInputDescription() { + return ""; + } + } +} 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 f1e24b620f01bfd682221f68b6cb7407f5ccac30..8265d0daad743fd31606eca36322bfbe3c7629ab 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 @@ -341,6 +341,8 @@ public class TestFunctions extends TestBase { assertEval("{ f <- function(a, barg, bextra, dummy) { a + barg } ; g <- function(...) { f(a=1, ...,,,) } ; g(1) }"); assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ f <- function(...) { ..2 + ..2 } ; f(1,,2) }"); assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ f <- function(...) { ..1 + ..2 } ; f(1,,3) }"); + + assertEval("{ f1 <- function(...) { subst <- substitute(list(...))[-1L]; eval(subst[[1]]) }; f2 <- function(a, ...) TRUE; f3 <- function(a, ...) { cat(\"Here:\"); f1(f2(a, ...)) }; f1(f3(\"aaa\")) }"); } @Test @@ -374,6 +376,11 @@ public class TestFunctions extends TestBase { assertEval(Ignored.Unstable, "{ exists }"); } + @Test + public void testFunctionResultPrinting() { + assertEval("{ foo <- function() { x <- 1; return(x) }; foo() }"); + } + @Test public void testIsPrimitive() { assertEval("{ is.primitive(is.primitive) }"); @@ -382,8 +389,8 @@ public class TestFunctions extends TestBase { @Test public void testDefaultArgs() { - assertEval(Output.IgnoreErrorContext, "{ array(dim=c(-2,2)); }"); - assertEval(Output.IgnoreErrorContext, "{ array(dim=c(-2,-2)); }"); + assertEval("{ array(dim=c(-2,2)); }"); + assertEval("{ array(dim=c(-2,-2)); }"); assertEval("{ length(array(dim=c(1,0,2,3))) }"); assertEval("{ dim(array(dim=c(2.1,2.9,3.1,4.7))) }"); } 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 eec8974833cac7fa384d397106682b90355d237b..0b51a3d92da5c30b1872b21f4e31c429aeaa6403 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 @@ -36,6 +36,7 @@ import com.oracle.truffle.api.debug.SuspendedEvent; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.vm.PolyglotEngine; import com.oracle.truffle.r.runtime.ExitException; +import com.oracle.truffle.r.runtime.JumpToTopLevelException; import com.oracle.truffle.r.runtime.RCmdOptions; import com.oracle.truffle.r.runtime.RCmdOptions.Client; import com.oracle.truffle.r.runtime.RError; @@ -224,8 +225,9 @@ public final class FastRSession implements RSession { } } catch (ParseException e) { e.report(consoleHandler); - } catch (ExitException e) { - // exit exceptions are legitimate if a test case calls "q()" + } catch (ExitException | JumpToTopLevelException e) { + // exit and jumpToTopLevel exceptions are legitimate if a test case calls "q()" or "Q" + // during debugging } catch (RError e) { // nothing to do } catch (Throwable t) { diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConditionHandling.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConditionHandling.java index 8d7b2dcf1abc33ede8b98aa6ddc300275d0c5df2..c2c416bad75f8e020b1eb20d5e8591bfcfaa132b 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConditionHandling.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConditionHandling.java @@ -63,5 +63,7 @@ public class TestConditionHandling extends TestRBase { assertEval("withCallingHandlers({message(\"foo\");123L},\n message=function(e) {cat(\"<msg>\")})"); assertEval("withCallingHandlers({message(\"foo\");123L},\n message=function(e) {\n cat(\"<msg>\")\n invokeRestart(\"muffleMessage\")\n })"); assertEval("withCallingHandlers({message(\"foo\");packageStartupMessage(\"bar\");123L},\n packageStartupMessage=function(e) {\n cat(\"<msg>\")\n invokeRestart(\"muffleMessage\")\n })"); + assertEval(Output.IgnoreErrorContext, "withCallingHandlers(stop('error message'), error=function(e) {})"); + assertEval(Output.IgnoreErrorMessage, "withCallingHandlers(unknownSymbol(), condition = function(e) {})"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java index b67b54e5a1ce70a0ad76d64d77ea2448218bac18..f1aeb3cf9e11661412dc09a88db57544465fb977 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java @@ -22,15 +22,24 @@ */ package com.oracle.truffle.r.test.library.base; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.zip.GZIPOutputStream; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import com.oracle.truffle.r.test.TestBase; +import com.oracle.truffle.r.test.TestRBase; -public class TestConnections extends TestBase { +// Checkstyle: stop line length check +public class TestConnections extends TestRBase { private static final class TestDir { private final Path testDirPath; @@ -44,17 +53,30 @@ public class TestConnections extends TestBase { } private static TestDir testDir; + private static Path tempFileGzip; + + @Override + protected String getTestDir() { + return "builtins/connection"; + } @BeforeClass - public static void setupTestDir() { + public static void setup() throws IOException { testDir = new TestDir(); + + // create a gzipped file + tempFileGzip = Paths.get("gzipped_____5137528280012599068___.gz"); + OutputStream gzos = new GZIPOutputStream(Files.newOutputStream(tempFileGzip, StandardOpenOption.WRITE, StandardOpenOption.CREATE)); + gzos.write("Hello, World!".getBytes()); + gzos.close(); } @AfterClass - public static void teardownTestDir() { + public static void teardown() { if (!deleteDir(testDir.testDirPath)) { System.err.println("WARNING: error deleting : " + testDir.testDirPath); } + deleteDir(tempFileGzip); } @Test @@ -71,10 +93,15 @@ public class TestConnections extends TestBase { assertEval(TestBase.template("{ readChar(file(\"%0\"), 3) }", testDir.subDir("wc1"))); } - @Test + @Test(timeout = 1000) public void testFileWriteReadBin() { assertEval(TestBase.template("{ writeBin(\"abc\", file(\"%0\", open=\"wb\")) }", testDir.subDir("wb1"))); assertEval(TestBase.template("{ readBin(file(\"%0\", \"rb\"), 3) }", testDir.subDir("wb1"))); + + assertEval(TestBase.template("{ zz <- file(\"%0\", open=\"wb\"); writeChar(\"abc\", zz); close(zz); readBin(file(\"%0\", \"rb\"), character(), 4) }", testDir.subDir("wb2"))); + + // incomplete line at the end of file + assertEval(TestBase.template("{ cat('abc', file = '%0'); readBin(file('%0', 'rb'), character(), 2) }", testDir.subDir("wb3"))); } @Test @@ -84,6 +111,8 @@ public class TestConnections extends TestBase { @Test public void testTextReadConnection() { + assertEval(Output.IgnoreErrorContext, "textConnection(NULL, 'r')"); + assertEval("{ con <- textConnection(c(\"1\", \"2\", \"3\",\"4\")); readLines(con) }"); assertEval("{ con <- textConnection(c(\"1\", \"2\", \"3\",\"4\")); readLines(con, 2) }"); assertEval("{ con <- textConnection(c(\"1\", \"2\", \"3\",\"4\")); readLines(con, 2); readLines(con, 2) }"); @@ -114,13 +143,131 @@ public class TestConnections extends TestBase { } @Test - public void testWriteConnection() { + public void testWriteTextConnection() { assertEval("{ con <- textConnection(\"tcval\", open=\"w\"); writeLines(\"a\", con); tcval; close(con) }"); assertEval("{ con <- textConnection(\"tcval\", open=\"w\"); writeLines(\"a\", con); writeLines(c(\"a\", \"b\"), con, sep=\".\"); tcval; close(con) }"); assertEval("{ con <- textConnection(\"tcval\", open=\"w\"); writeLines(\"a\", con); writeLines(c(\"a\", \"b\"), con, sep=\".\"); writeLines(\"\", con); tcval; close(con) }"); assertEval("{ con <- textConnection(\"tcval\", open=\"w\"); writeLines(\"a\\nb\", con); tcval; close(con) }"); - assertEval(Ignored.Unimplemented, "c <- textConnection('out', 'w'); cat('testtext', file=c); isIncomplete(c); cat('testtext2\\n', file=c); isIncomplete(c); close(c); out"); + assertEval("c <- textConnection('out', 'w'); cat('testtext', file=c); isIncomplete(c); cat('testtext2\\n', file=c); isIncomplete(c); close(c); out"); + + // anonymous connection + assertEval("{ c <- textConnection(NULL, 'w'); cat('testtext\\n', file=c); textConnectionValue(c) }"); assertEval("{ d<-data.frame(c(1,2), c(10, 20)); buf<-character(); c<-textConnection(\"buf\", open=\"w\", local=T); write.table(d, c); buf }"); } + + @Test + public void testSeekTextConnection() { + assertEval("{ zz <- textConnection(\"Hello, World!\"); res <- isSeekable(zz); close(zz); res }"); + assertEval(Output.IgnoreErrorMessage, "{ zz <- textConnection(\"Hello, World!\"); res <- seek(zz, 5); close(zz); res }"); + } + + @Test + public void testFileSummary() { + Assert.assertTrue("Could not create required temp file for test.", Files.exists(tempFileGzip)); + assertEval("{ zz <- file(\"" + tempFileGzip + "\", \"r\"); res <- summary(zz); close(zz); res }"); + + assertEval("zz <- file('', 'w+'); summary(zz); close(zz)"); + } + + @Test + public void testReopen() { + assertEval("{ con <- rawConnection(charToRaw('hello\\nworld\\n')); readLines(con, 1); open(con, 'rb'); bin <- readBin(con, raw(), 999); close(con); rawToChar(bin) }"); + } + + @Test + public void testFileOpenRaw() { + Assert.assertTrue("Could not create required temp file for test.", Files.exists(tempFileGzip)); + assertEval("{ zz <- file(\"" + tempFileGzip + "\", \"r\", raw=T); res <- readBin(zz, raw(), 4); close(zz); res }"); + assertEval("{ zz <- rawConnection(as.raw(c(65, 66, 67, 0, 97, 98, 99))); readChar(zz, 6) }"); + } + + @Test + public void testEncoding() { + // use inexisting charset + assertEval("fin <- file('', \"w+\", encoding = \"___inexistingCharSet___\")"); + + // write UTF-8 file + assertEval("{ wline <- 'Hellö'; fin <- file('', 'w+', encoding = 'UTF-8'); writeLines(wline, fin); seek(fin, 0); rline <- readLines(fin, 1); close(fin); c(wline, rline, wline == rline) }"); + } + + @Test + public void testReadLines() { + // one line containing '\0' + final String lineWithNul = "c(97,98,99,100,0,101,10)"; + + // two lines, first containing '\0' + final String twoLinesOneNul = "c(97,98,99,100,0,101,10,65,66,67,10)"; + + // one line containing '\0' and imcomplete + final String lineWithNulIncomp = "c(97,98,99,100,0,101)"; + + // two lines, first containing '\0', second line incomplete + final String twoLinesOneNulIncomp = "c(97,98,99,100,0,101,10,65,66,67)"; + + assertEval(Output.MayIgnoreWarningContext, TestBase.template( + "{ zz <- file('',\"w+b\", blocking=%0); writeBin(as.raw(%1), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=%2, skipNul=%3); close(zz); res }", + LVAL, arr(lineWithNul, twoLinesOneNul, lineWithNulIncomp, twoLinesOneNulIncomp), LVAL, LVAL)); + } + + @Test + public void testRawReadAppendText() { + + assertEval("{ rc <- rawConnection(raw(0), \"a+\"); close(rc); write(charToRaw(\"A\"), rc) }"); + assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"a+\"); writeChar(\", World\", rc); res <- rawConnectionValue(rc); close(rc); res }"); + assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"a+\"); writeChar(\", World\", rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }"); + assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"a+\"); write(charToRaw(\", World\"), rc); res <- rawConnectionValue(rc); close(rc); res }"); + assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"a+\"); write(charToRaw(\", World\"), rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }"); + } + + @Test + public void testRawReadWriteText() { + + assertEval("{ rc <- rawConnection(raw(0), \"r+\"); close(rc); write(charToRaw(\"A\"), rc) }"); + assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"r+\"); writeChar(\", World\", rc); res <- rawConnectionValue(rc); close(rc); res }"); + assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"r+\"); writeChar(\", World\", rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }"); + assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"r+\"); write(charToRaw(\", World\"), rc); res <- rawConnectionValue(rc); close(rc); res }"); + assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"r+\"); write(charToRaw(\", World\"), rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }"); + } + + @Test + public void testRawWriteText() { + + assertEval("{ s <- \"äöüß\"; rc <- rawConnection(raw(0), \"w\"); writeChar(s, rc); rawConnectionValue(rc) }"); + assertEval("{ rc <- rawConnection(raw(0), \"w\"); writeChar(\"Hello\", rc); writeChar(\", World\", rc); res <- rawConnectionValue(rc); close(rc); res }"); + } + + @Test + public void testRawWriteBinary() { + + // this test is currently ignored, since 'charToRaw' is not compliant + assertEval(Ignored.ImplementationError, "{ s <- \"äöüß\"; rc <- rawConnection(raw(0), \"wb\"); write(charToRaw(s), rc); res <- rawConnectionValue(rc); close(rc); res }"); + assertEval("{ zz <- rawConnection(raw(0), \"wb\"); x <- c(\"a\", \"this will be truncated\", \"abc\"); nc <- c(3, 10, 3); writeChar(x, zz, nc, eos = NULL); writeChar(x, zz, eos = \"\\r\\n\"); res <- rawConnectionValue(zz); close(zz); res }"); + + assertEval("conn <- rawConnection(raw(0), \"wb\"); value <- list(a=c(1,2,3), b='foo'); save(value, file=conn); rawConnectionValue(conn)"); + // ignored because save refuses to write to a rawConnection that is not configured to binary + assertEval(Ignored.ImplementationError, "conn <- rawConnection(raw(0), \"w\"); value <- c(1,2,3); save(value, file=conn); rawConnectionValue(conn)"); + } + + @Test + public void testFifoOpenInexisting() { + assertEval("capabilities(\"fifo\")"); + assertEval("{ fn <- '___fifo_2367253765'; zz <- fifo(fn, 'r', blocking = TRUE); close(zz); unlink(fn) }"); + } + + public void testTruncate() { + assertEval("truncate(pipe('ls'))"); + assertEval("zz <- file(''); writeLines(c('Hello', 'wonderful', 'World'), zz); seek(zz, 0); truncate(zz); flush(zz); readLines(zz)"); + assertEval("fn <- '__tmp_77253842367367'; zz <- file(fn, 'w'); writeLines(c('Hello', 'wonderful', 'World'), zz); seek(zz, 0); truncate(zz); close(zz); readLines(file(fn)); unlink(fn)"); + assertEval("fn <- '__tmp_98723669834556'; zz <- file(fn, 'w'); writeLines(c('Hello', 'wonderful', 'World'), zz); close(zz); zz <- file(fn, 'r'); truncate(zz); unlink(fn)"); + assertEval("zz <- rawConnection(raw(0), 'r+'); writeLines(c('hello', 'world'), zz); rawConnectionValue(zz); seek(zz, 5); truncate(zz); rawConnectionValue(zz); close(zz)"); + assertEval("truncate(fifo('__fifo_872636743', 'w+', blocking=T)); unlink('__fifo_872636743')"); + assertEval("truncate(fifo('__fifo_982346798', 'r', blocking=T)); unlink('__fifo_982346798')"); + } + + private static final String[] LVAL = arr("T", "F"); + + private static String[] arr(String... args) { + return args; + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestPromiseOptimizations.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestPromiseOptimizations.java index 07a77a76c6f0b696d76f78f977729def6d88d7ec..b15e3ead2cde8cf51f1cd03d55d61d3f29804c2f 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestPromiseOptimizations.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestPromiseOptimizations.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 @@ -61,5 +61,11 @@ public class TestPromiseOptimizations extends TestBase { // "delayedAssign" RFunction: (Special case of but handled by: delayedAssign) assertEval("{ f <- function(x) { delayedAssign('b', function() {x}, sys.frame(sys.nframe()), parent.frame()); } ; a <- 1 ; f( a ) ; a <- 10 ; b() }"); + + // the value of 'pi' promise may look like temporary vector, but the arithmetic operation + // must not re-use it for the result + assertEval("{ pi/180; pi }"); + // similar situation as above + assertEval("{ delayedAssign('x', c(1,2,3)); x/180; x }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArithmetic.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArithmetic.java index acef8ebf71b959321af693c36a35f6dd97cad904..59bec36ada508d1cdba82db2c227ed96aa648861 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArithmetic.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArithmetic.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -320,10 +320,10 @@ public class TestSimpleArithmetic extends TestBase { @Test public void testVectorsLengthWarning() { - assertEval(Output.IgnoreWarningContext, "{ 1:2+1:3 }"); - assertEval(Output.IgnoreWarningContext, "{ 1:3*1:2 }"); - assertEval(Output.IgnoreWarningContext, "{ 1:3+c(1,2+2i) }"); - assertEval(Output.IgnoreWarningContext, "{ c(1,2+2i)+1:3 }"); + assertEval("{ 1:2+1:3 }"); + assertEval("{ 1:3*1:2 }"); + assertEval("{ 1:3+c(1,2+2i) }"); + assertEval("{ c(1,2+2i)+1:3 }"); } @Test @@ -612,11 +612,11 @@ public class TestSimpleArithmetic extends TestBase { @Test public void testNonvectorizedLogicalLengthChecks() { - assertEval(Output.IgnoreWarningContext, "{ as.raw(c(1,4)) | as.raw(c(1,5,4)) }"); - assertEval(Output.IgnoreWarningContext, "{ as.raw(c(1,5,4)) | as.raw(c(1,4)) }"); - assertEval(Output.IgnoreWarningContext, "{ c(TRUE, FALSE, FALSE) & c(TRUE,TRUE) }"); - assertEval(Output.IgnoreWarningContext, "{ c(TRUE, TRUE) & c(TRUE, FALSE, FALSE) }"); - assertEval(Output.IgnoreWarningContext, "{ c(a=TRUE, TRUE) | c(TRUE, b=FALSE, FALSE) }"); + assertEval("{ as.raw(c(1,4)) | as.raw(c(1,5,4)) }"); + assertEval("{ as.raw(c(1,5,4)) | as.raw(c(1,4)) }"); + assertEval("{ c(TRUE, FALSE, FALSE) & c(TRUE,TRUE) }"); + assertEval("{ c(TRUE, TRUE) & c(TRUE, FALSE, FALSE) }"); + assertEval("{ c(a=TRUE, TRUE) | c(TRUE, b=FALSE, FALSE) }"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArrays.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArrays.java index 1c0d9daf0f662dc91a599494d0f38882d36b1a20..b2b0daed5ffd38f792a946a80800a72b3a3850f3 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArrays.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArrays.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -89,10 +89,10 @@ public class TestSimpleArrays extends TestBase { // negative length vectors are not allowed is the error reported by gnu-r // negative dims not allowed by R, special GNU message - assertEval(Output.IgnoreErrorContext, "{ array(NA, dim=c(-2,2)); }"); + assertEval("{ array(NA, dim=c(-2,2)); }"); // negative dims not allowed - assertEval(Output.IgnoreErrorContext, "{ array(NA, dim=c(-2,-2)); }"); + assertEval("{ array(NA, dim=c(-2,-2)); }"); // zero dimension array has length 0 assertEval("{ length(array(NA, dim=c(1,0,2,3))) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleComparison.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleComparison.java index 5ba65d71309ea91be5601b9baaaf5d23fe573e21..163f682083d4445a11389d70e0d71dd1580a4724 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleComparison.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleComparison.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -209,18 +209,18 @@ public class TestSimpleComparison extends TestBase { assertEval("{ 1:3 == TRUE }"); assertEval("{ TRUE == 1:3 }"); - assertEval(Output.IgnoreWarningContext, "{ c(1,2) < c(2,1,4) }"); - assertEval(Output.IgnoreWarningContext, "{ c(2,1,4) < c(1,2) }"); - assertEval(Output.IgnoreWarningContext, "{ c(1L,2L) < c(2L,1L,4L) }"); - assertEval(Output.IgnoreWarningContext, "{ c(2L,1L,4L) < c(1L,2L) }"); - assertEval(Output.IgnoreWarningContext, "{ c(TRUE,FALSE,FALSE) < c(TRUE,TRUE) }"); - assertEval(Output.IgnoreWarningContext, "{ c(TRUE,TRUE) == c(TRUE,FALSE,FALSE) }"); - assertEval(Output.IgnoreWarningContext, "{ as.raw(c(1,2)) < as.raw(c(2,1,4)) }"); - assertEval(Output.IgnoreWarningContext, "{ as.raw(c(2,1,4)) < as.raw(c(1,2)) }"); - assertEval(Output.IgnoreWarningContext, "{ c(\"hi\",\"hello\",\"bye\") > c(\"cau\", \"ahoj\") }"); - assertEval(Output.IgnoreWarningContext, "{ c(\"cau\", \"ahoj\") != c(\"hi\",\"hello\",\"bye\") }"); - assertEval(Output.IgnoreWarningContext, "{ c(1+1i,2+2i) == c(2+1i,1+2i,1+1i) }"); - assertEval(Output.IgnoreWarningContext, "{ c(2+1i,1+2i,1+1i) == c(1+1i, 2+2i) }"); + assertEval("{ c(1,2) < c(2,1,4) }"); + assertEval("{ c(2,1,4) < c(1,2) }"); + assertEval("{ c(1L,2L) < c(2L,1L,4L) }"); + assertEval("{ c(2L,1L,4L) < c(1L,2L) }"); + assertEval("{ c(TRUE,FALSE,FALSE) < c(TRUE,TRUE) }"); + assertEval("{ c(TRUE,TRUE) == c(TRUE,FALSE,FALSE) }"); + assertEval("{ as.raw(c(1,2)) < as.raw(c(2,1,4)) }"); + assertEval("{ as.raw(c(2,1,4)) < as.raw(c(1,2)) }"); + assertEval("{ c(\"hi\",\"hello\",\"bye\") > c(\"cau\", \"ahoj\") }"); + assertEval("{ c(\"cau\", \"ahoj\") != c(\"hi\",\"hello\",\"bye\") }"); + assertEval("{ c(1+1i,2+2i) == c(2+1i,1+2i,1+1i) }"); + assertEval("{ c(2+1i,1+2i,1+1i) == c(1+1i, 2+2i) }"); assertEval("{ as.raw(c(2,1,4)) < raw() }"); assertEval("{ raw() < as.raw(c(2,1,4)) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleDataFrames.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleDataFrames.java index 0abd003a95ce7e5d3de664d3c8af3cb93e3212e8..bec24a898263ffa10c0fab5fb99cb272c2af8efb 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleDataFrames.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleDataFrames.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 @@ -100,9 +100,9 @@ public class TestSimpleDataFrames extends TestBase { assertEval("{ x<-as.character(c(7L,42L)); y<-as.data.frame(x, row.names=NULL, nm=\"x\"); is.data.frame(y); }"); assertEval("{ x<-as.complex(c(7L,42L)); y<-as.data.frame(x, row.names=NULL, nm=\"x\"); is.data.frame(y); }"); assertEval("{ x<-as.raw(c(7L,42L)); y<-as.data.frame(x, row.names=NULL, nm=\"x\"); is.data.frame(y); }"); - assertEval(Output.IgnoreWarningContext, "{ x<-c(7L,42L); y<-as.data.frame(x, row.names=\"r1\", nm=\"x\"); attributes(y); }"); + assertEval(Output.MayIgnoreWarningContext, "{ x<-c(7L,42L); y<-as.data.frame(x, row.names=\"r1\", nm=\"x\"); attributes(y); }"); assertEval("{ x<-c(7L,42L); y<-as.data.frame(x, row.names=c(\"r1\", \"r2\"), nm=\"x\"); attributes(y); }"); - assertEval(Output.IgnoreWarningContext, "{ x<-c(7L,42L); y<-as.data.frame(x, row.names=c(\"r1\", \"r2\", \"r3\"), nm=\"x\"); attributes(y); }"); + assertEval(Output.MayIgnoreWarningContext, "{ x<-c(7L,42L); y<-as.data.frame(x, row.names=c(\"r1\", \"r2\", \"r3\"), nm=\"x\"); attributes(y); }"); assertEval("{ x<-matrix(c(1,2,3,4), nrow=2); y<-as.data.frame(x, row.names=NULL, optional=FALSE); attributes(y); }"); assertEval("{ x<-matrix(c(1,2,3,4), nrow=2); y<-as.data.frame(x, row.names=\"r1\", optional=FALSE); attributes(y); }"); assertEval("{ x<-1; class(x)<-\"foo\"; y<-as.data.frame(x) }"); @@ -179,5 +179,6 @@ public class TestSimpleDataFrames extends TestBase { assertEval("{ y<-data.frame(c(1,2,3)); length(y) }"); + assertEval("x <- data.frame(a=1:3,b=factor(c(\"a\",\"b\",\"c\"))); x[2,]"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java index 9ed8cb3b99b6c99eb053eb20a7cd287ddb6e7f75..60dc992cb1c4a89329dfdfd6dad428c00a7ad884 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -51,45 +51,45 @@ public class TestSimpleIfEvaluator extends TestBase { @Test public void testIf() { assertEval("{ x <- 2 ; if (1==x) TRUE else 2 }"); - assertEval(Output.IgnoreErrorContext, "{ x <- 2 ; if (NA) x <- 3 ; x }"); - assertEval(Output.IgnoreErrorContext, "{ f <- function(x) { if (x) 1 else 2 } ; f(NA) }"); - assertEval(Output.IgnoreErrorContext, "{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(NA) }"); + assertEval("{ x <- 2 ; if (NA) x <- 3 ; x }"); + assertEval("{ f <- function(x) { if (x) 1 else 2 } ; f(NA) }"); + assertEval("{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(NA) }"); assertEval("{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(TRUE) }"); assertEval("{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(FALSE) }"); - assertEval(Output.IgnoreErrorContext, "{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(\"hello\") }"); - assertEval(Output.IgnoreErrorContext, "{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(logical()) }"); - assertEval(Output.IgnoreErrorContext, "{ f <- function(x) { if (x == 2) 1 else 2 } ; f(1) ; f(NA) }"); + assertEval("{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(\"hello\") }"); + assertEval("{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(logical()) }"); + assertEval("{ f <- function(x) { if (x == 2) 1 else 2 } ; f(1) ; f(NA) }"); assertEval("{ if (TRUE==FALSE) TRUE else FALSE }"); - assertEval(Output.IgnoreErrorContext, "{ if (NA == TRUE) TRUE else FALSE }"); - assertEval(Output.IgnoreErrorContext, "{ if (TRUE == NA) TRUE else FALSE }"); + assertEval("{ if (NA == TRUE) TRUE else FALSE }"); + assertEval("{ if (TRUE == NA) TRUE else FALSE }"); assertEval("{ if (FALSE==TRUE) TRUE else FALSE }"); assertEval("{ if (FALSE==1) TRUE else FALSE }"); assertEval("{ f <- function(v) { if (FALSE==v) TRUE else FALSE } ; f(TRUE) ; f(1) }"); - assertEval(Output.IgnoreErrorContext, Output.IgnoreWarningContext, "{ x<-list(1,2); if (x) 7 else 42 }"); + assertEval("{ x<-list(1,2); if (x) 7 else 42 }"); assertEval("{ if (!(7+42i)) TRUE else FALSE }"); } @Test public void testIfIgnore() { - assertEval(Output.IgnoreWarningContext, "{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(1:3) }"); + assertEval("{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(1:3) }"); } @Test public void testCast() { - assertEval(Output.IgnoreWarningContext, "{ f <- function(a) { if (is.na(a)) { 1 } else { 2 } } ; f(5) ; f(1:3)}"); - assertEval(Output.IgnoreWarningContext, "{ if (1:3) { TRUE } }"); - assertEval(Output.IgnoreErrorContext, "{ if (integer()) { TRUE } }"); - assertEval(Output.IgnoreErrorContext, "{ if (1[2:1]) { TRUE } }"); - assertEval(Output.IgnoreWarningContext, "{ if (c(0,0,0)) { TRUE } else { 2 } }"); - assertEval(Output.IgnoreWarningContext, "{ if (c(1L,0L,0L)) { TRUE } else { 2 } }"); - assertEval(Output.IgnoreWarningContext, "{ if (c(0L,0L,0L)) { TRUE } else { 2 } }"); - assertEval(Output.IgnoreErrorContext, "{ if (c(1L[2],0L,0L)) { TRUE } else { 2 } }"); - assertEval(Output.IgnoreWarningContext, "{ f <- function(cond) { if (cond) { TRUE } else { 2 } } ; f(1:3) ; f(2) }"); - assertEval(Output.IgnoreWarningContext, "{ f <- function(cond) { if (cond) { TRUE } else { 2 } } ; f(c(TRUE,FALSE)) ; f(FALSE) }"); - assertEval(Output.IgnoreErrorContext, "{ f <- function(cond) { if (cond) { TRUE } else { 2 } } ; f(logical()) }"); - assertEval(Output.IgnoreWarningContext, "{ f <- function(cond) { if (cond) { TRUE } else { 2 } } ; f(c(TRUE,FALSE)) ; f(1) }"); + assertEval("{ f <- function(a) { if (is.na(a)) { 1 } else { 2 } } ; f(5) ; f(1:3)}"); + assertEval("{ if (1:3) { TRUE } }"); + assertEval("{ if (integer()) { TRUE } }"); + assertEval("{ if (1[2:1]) { TRUE } }"); + assertEval("{ if (c(0,0,0)) { TRUE } else { 2 } }"); + assertEval("{ if (c(1L,0L,0L)) { TRUE } else { 2 } }"); + assertEval("{ if (c(0L,0L,0L)) { TRUE } else { 2 } }"); + assertEval("{ if (c(1L[2],0L,0L)) { TRUE } else { 2 } }"); + assertEval("{ f <- function(cond) { if (cond) { TRUE } else { 2 } } ; f(1:3) ; f(2) }"); + assertEval("{ f <- function(cond) { if (cond) { TRUE } else { 2 } } ; f(c(TRUE,FALSE)) ; f(FALSE) }"); + assertEval("{ f <- function(cond) { if (cond) { TRUE } else { 2 } } ; f(logical()) }"); + assertEval("{ f <- function(cond) { if (cond) { TRUE } else { 2 } } ; f(c(TRUE,FALSE)) ; f(1) }"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLists.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLists.java index d0add2169743d95cfebce812ad9a3e8811a81da6..f9391d284b4f51face32cb1f3bfc3c960199a5a8 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLists.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLists.java @@ -48,10 +48,14 @@ public class TestSimpleLists extends TestBase { assertEval(Output.IgnoreErrorContext, "{ l <- list(1,2,3) ; l[[0]] }"); assertEval("{ l <- list(1,2,3) ; l[[NA]] }"); + assertEval("{ l <- list(1,2,3) ; l[[NaN]] }"); assertEval("{ l <- list(1,2,3) ; typeof(l[[NA]]) }"); + assertEval("{ l <- list(1,2,3) ; typeof(l[[NaN]]) }"); assertEval("{ l <- list(1,2,3) ; l[NA] }"); + assertEval("{ l <- list(1,2,3) ; l[NaN] }"); assertEval("{ l <- list(1,2,3) ; typeof(l[NA]) }"); + assertEval("{ l <- list(1,2,3) ; typeof(l[NaN]) }"); assertEval("{ l <- list(1,2,3) ; l[-2] }"); assertEval("{ l <- list(1,2,3) ; typeof(l[-2]) }"); @@ -158,7 +162,7 @@ public class TestSimpleLists extends TestBase { assertEval("a<- NULL; a <- `$<-`(a, \"a\", 1); dput(a)"); assertEval("a<- NULL; a <- `[[<-`(a, \"a\", 1); dput(a)"); assertEval("a<- NULL; a <- `[[<-`(a, 1, 1); dput(a)"); - assertEval("a<- NULL; a <- `$<-`(a, 1, 1); dput(a)"); + // FastR produces a better error context + assertEval(Output.IgnoreErrorContext, "a<- NULL; a <- `$<-`(a, 1, 1); dput(a)"); } - } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLoop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLoop.java index 15e11180f0c429e27a972e462b9fca4d62f53d8b..2c34e86d420894383b06e50a313d8a9baa3faa0f 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLoop.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLoop.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -49,7 +49,7 @@ public class TestSimpleLoop extends TestBase { @Test public void testLoopsErrors() { - assertEval(Output.IgnoreErrorContext, "{ while (1 < NA) { 1 } }"); + assertEval("{ while (1 < NA) { 1 } }"); assertEval("{ break; }"); assertEval("{ next; }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleMatrix.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleMatrix.java index 3ce0c94e121bdec3c9513f145bb29bd30e779cda..2324ef9e6a20866630ffb26c887719c95db85774 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleMatrix.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleMatrix.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 @@ -82,8 +82,11 @@ public class TestSimpleMatrix extends TestBase { assertEval(template("{ x<-%0; dim(x)<-c(1,4); dimnames(x)<-list(\"z\", c(\"a\", \"b\", \"c\", \"d\")); x[1, c(1,3)] }", TESTED_4L_VECTORS)); assertEval(template("{ x<-%0; dim(x)<-c(1,4); dimnames(x)<-list(\"z\", c(\"a\", \"b\", \"d\", \"e\")); x[1, c(1,3)] }", TESTED_4L_VECTORS)); assertEval(template("{ x<-%0; dim(x)<-c(2,2); x[c(1, NA), ] }", TESTED_4L_VECTORS)); + assertEval(template("{ x<-%0; dim(x)<-c(2,2); x[c(1, NaN), ] }", TESTED_4L_VECTORS)); assertEval(template("{ x<-%0; dim(x)<-c(2,2); x[c(TRUE, NA), ] }", TESTED_4L_VECTORS)); + assertEval(template("{ x<-%0; dim(x)<-c(2,2); x[c(TRUE, NaN), ] }", TESTED_4L_VECTORS)); assertEval(template("{ x<-%0; x<-1:4; dim(x)<-c(2,2); x[NA, ] }", TESTED_4L_VECTORS)); + assertEval(template("{ x<-%0; x<-1:4; dim(x)<-c(2,2); x[NaN, ] }", TESTED_4L_VECTORS)); // A misalignment error similar to those in TestSimpleVector (testIgnored1-3) WhiteList wl = WhiteList.create("matrix formatting1"); wl.add("{ x<-c(as.raw(1),as.raw(2),as.raw(3),as.raw(4)); dim(x)<-c(2,2); dimnames(x)<-list(c(\"a\", \"b\"), c(\"c\", \"d\")); x[c(1,NA), 1] }", diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleTruffle.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleTruffle.java index 75b2a0d373e0fd42668449234689a7b68b55a5b6..8112db7c94d83cf535f6c2863e285aa3eb9b46b2 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleTruffle.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleTruffle.java @@ -4,7 +4,7 @@ * http://www.gnu.org/licenses/gpl-2.0.html * * Copyright (c) 2012-2014, Purdue University - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -53,7 +53,7 @@ public class TestSimpleTruffle extends TestBase { @Test public void testWarningsAndErrors() { assertEval("{ (c(1, 2) < c(1, 2, 3)) == (c(1, 2) < c(1, 3, 4)) }"); - assertEval(Output.IgnoreErrorContext, Output.IgnoreWarningContext, "{ 1i > (c(1, 2) < c(1, 2, 3)) }"); + assertEval("{ 1i > (c(1, 2) < c(1, 2, 3)) }"); assertEval("{ 1i > ((c(1, 2) < c(1, 2, 3)) == (c(1, 2) < c(1, 3, 4))) }"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java index 8c765123f626cab21d83098d7de3a2e045bae47e..60ee20a4efe1edc0bf42bcdaa0f7de9c424638ed 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java @@ -162,6 +162,7 @@ public class TestSimpleVectors extends TestBase { assertEval("{ x<-3:1; x[1L] }"); assertEval("{ x<-3:1; x[2L] }"); assertEval("{ x<-3:1; x[3L] }"); + assertEval("{ x<-3:1; x[NA_integer_] }"); } @Test @@ -192,6 +193,8 @@ public class TestSimpleVectors extends TestBase { assertEval("{ x<-3:1; x[1.1] }"); assertEval("{ x<-3:1; x[2.1] }"); assertEval("{ x<-3:1; x[3.1] }"); + assertEval("{ x<-3:1; x[NaN] }"); + assertEval("{ x<-3:1; x[NA_real_] }"); } @Test @@ -225,6 +228,7 @@ public class TestSimpleVectors extends TestBase { assertEval("{ x<-NULL; x[1L] }"); assertEval("{ x<-NULL; x[2L] }"); assertEval("{ x<-NULL; x[3L] }"); + assertEval("{ x<-NULL; x[NaN] }"); assertEval("{ x<-1.1:3.1; x[1L] }"); assertEval("{ x<-1.1:3.1; x[2L] }"); assertEval("{ x<-1.1:3.1; x[3L] }"); @@ -242,7 +246,10 @@ public class TestSimpleVectors extends TestBase { assertEval("{ x<-1L; x[-2L] }"); assertEval("{ x<-1L; x[TRUE] }"); assertEval("{ x<-1L; x[FALSE] }"); + assertEval("{ x<-1L; x[NA_real_] }"); + assertEval("{ x<-1L; x[NA_integer_] }"); assertEval("{ x<-1L; x[NA] }"); + assertEval("{ x<-1L; x[NaN] }"); } @Test @@ -262,6 +269,7 @@ public class TestSimpleVectors extends TestBase { assertEval("{ x<-1; x[TRUE] }"); assertEval("{ x<-1; x[FALSE] }"); assertEval("{ x<-1; x[NA] }"); + assertEval("{ x<-1; x[NaN] }"); } @Test @@ -382,7 +390,7 @@ public class TestSimpleVectors extends TestBase { assertEval("{ l<-list(1,2,3,4); l[[c(2,1)]]<-7; l }"); assertEval("{ l<-list(1,2,3,4); l[c(2,1)]<-7; l }"); - assertEval(Output.IgnoreWarningContext, "{ x<-1:4; x[1]<-c(1,1); x }"); + assertEval("{ x<-1:4; x[1]<-c(1,1); x }"); assertEval("{ x<-1:4; x[[1]]<-c(1,1); x }"); assertEval("{ x<-1; x[0]<-integer(); x }"); assertEval(Output.IgnoreErrorMessage, "{ x<-1; x[[0]]<-integer(); x }"); @@ -399,25 +407,31 @@ public class TestSimpleVectors extends TestBase { assertEval(Output.IgnoreErrorContext, "{ x<-7; x[[0]]<-42; x }"); assertEval("{ x<-1:4; x[c(1, 0)]<-42; x }"); assertEval("{ x<-1:4; x[c(0, 1)]<-42; x }"); - assertEval(Output.IgnoreWarningContext, "{ x<-1:4; x[c(1, 0)]<-c(7, 42); x }"); - assertEval(Output.IgnoreWarningContext, "{ x<-1:4; x[c(0, 1)]<-c(7, 42); x }"); + assertEval("{ x<-1:4; x[c(1, NA)]<-42; x }"); + assertEval("{ x<-1:4; x[c(1, NaN)]<-42; x }"); + assertEval("{ x<-1:4; x[c(NA, 1)]<-42; x }"); + assertEval("{ x<-1:4; x[c(NaN, 1)]<-42; x }"); + assertEval("{ x<-1:4; x[c(1, 0)]<-c(7, 42); x }"); + assertEval("{ x<-1:4; x[c(0, 1)]<-c(7, 42); x }"); assertEval("{ x<-1:4; dim(x)<-c(2,2); x[NULL]<-42; x }"); assertEval("{ x<-1:4; dim(x)<-c(2,2); x[NA]<-42; x }"); assertEval("{ x<-1:4; dim(x)<-c(2,2); x[0]<-42; x }"); assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(1,4)]<-c(42, 43); x }"); assertEval(Output.IgnoreErrorContext, "{ x<-1:4; dim(x)<-c(2,2); x[[c(1,4)]]<-c(42, 43); x }"); assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(1,NA)]<-c(42, 43); x }"); + assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(1,NaN)]<-c(42, 43); x }"); assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(NA,1)]<-c(42, 43); x }"); + assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(NaN,1)]<-c(42, 43); x }"); assertEval(Output.IgnoreErrorContext, "{ x<-1:4; dim(x)<-c(2,2); x[[c(1,0)]]<-c(42, 43); x }"); - assertEval(Output.IgnoreWarningContext, "{ x<-1:4; dim(x)<-c(2,2); x[c(1,0)]<-c(42, 43); x }"); + assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(1,0)]<-c(42, 43); x }"); assertEval(Output.IgnoreErrorContext, "{ x<-1:4; dim(x)<-c(2,2); x[[c(1,0,0)]]<-c(42, 43); x }"); - assertEval(Output.IgnoreWarningContext, "{ x<-1:4; dim(x)<-c(2,2); x[c(1,0,0)]<-c(42, 43); x }"); + assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(1,0,0)]<-c(42, 43); x }"); assertEval(Output.IgnoreErrorContext, "{ x<-1:4; dim(x)<-c(2,2); x[[c(1,1,0)]]<-c(42, 43); x }"); assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(1,1,0)]<-c(42, 43); x }"); assertEval(Output.IgnoreErrorMessage, "{ x<-1:4; dim(x)<-c(2,2); x[[c(0,1)]]<-c(42, 43); x }"); - assertEval(Output.IgnoreWarningContext, "{ x<-1:4; dim(x)<-c(2,2); x[c(0,1)]<-c(42, 43); x }"); + assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(0,1)]<-c(42, 43); x }"); assertEval(Output.IgnoreErrorMessage, "{ x<-1:4; dim(x)<-c(2,2); x[[c(0,0,1)]]<-c(42, 43); x }"); - assertEval(Output.IgnoreWarningContext, "{ x<-1:4; dim(x)<-c(2,2); x[c(0,0,1)]<-c(42, 43); x }"); + assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(0,0,1)]<-c(42, 43); x }"); assertEval(Output.IgnoreErrorMessage, "{ x<-1:4; dim(x)<-c(2,2); x[[c(0,1,1)]]<-c(42, 43); x }"); assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(0,1,1)]<-c(42, 43); x }"); assertEval(Output.IgnoreErrorMessage, "{ x<-1:4; dim(x)<-c(2,2); x[[c(0,0)]]<-c(42, 43); x }"); @@ -689,6 +703,9 @@ public class TestSimpleVectors extends TestBase { assertEval("{ e <- quote(f(x=a, y=b)); names(e[-1]) }"); assertEval("{ x<-quote(function(x, y) 42); x[[2]] }"); + assertEval("{ x<-quote(function(x, y) 42); x[2] }"); + assertEval("{ x<-quote(function(x, y) 42); x[NA] }"); + assertEval("{ x<-quote(function(x, y) 42); x[NaN] }"); assertEval("{ x<-quote(function(x, y) 42); typeof(x[[2]][[1]]) }"); assertEval("{ x<-quote(function(x, y) 42); names(x[[2]]) }"); assertEval("{ x<-quote(function(x, y=7) 42); x[[2]] }"); @@ -1432,7 +1449,7 @@ public class TestSimpleVectors extends TestBase { assertEval("{ x<-1:2; x[[0-2]]<-100; x }"); assertEval(Output.IgnoreErrorContext, "{ f <- function() { a[3] <- 4 } ; f() }"); - assertEval(Output.IgnoreWarningContext, "{ b <- c(1,2) ; z <- c(10,11) ; attr(z,\"my\") <- 4 ; b[2] <- z ; b }"); + assertEval("{ b <- c(1,2) ; z <- c(10,11) ; attr(z,\"my\") <- 4 ; b[2] <- z ; b }"); assertEval("{ b <- c(1,2) ; z <- b ; b[-2] <- 3L ; b }"); assertEval("{ b <- c(1,2) ; z <- b ; b[-10L] <- FALSE ; b }"); assertEval("{ b <- c(TRUE,NA) ; z <- b ; b[-10L] <- FALSE ; b }"); @@ -1723,17 +1740,17 @@ public class TestSimpleVectors extends TestBase { assertEval("{ b <- 3:4 ; b[c(NA)] <- c(2,7) ; b }"); assertEval("{ b <- 3:4 ; b[c(NA,1)] <- c(2,10) ; b }"); assertEval(Output.IgnoreErrorContext, "{ b <- 3:4 ; b[[c(NA,1)]] <- c(2,10) ; b }"); - assertEval(Output.IgnoreWarningContext, "{ b <- 3:4 ; b[c(0,1)] <- c(2,10,11) ; b }"); + assertEval("{ b <- 3:4 ; b[c(0,1)] <- c(2,10,11) ; b }"); assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(3:4, c(1,2), c(10,11)) ; f(4:5, as.integer(NA), 2) }"); assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(3:4, c(1,2), c(10,11)) ; f(4:5, c(1,-1), 2) }"); assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(3:4, c(1,2), c(10,11)) ; f(4:5, c(NA,-1), 2) }"); assertEval("{ b <- c(1,4,5) ; x <- c(2,8,2) ; b[x==2] <- c(10,11) ; b }"); assertEval("{ b <- c(1,4,5) ; z <- b ; x <- c(2,8,2) ; b[x==2] <- c(10,11) ; b }"); - assertEval(Output.IgnoreWarningContext, "{ b <- c(1,4,5) ; x <- c(2,2) ; b[x==2] <- c(10,11) ; b }"); + assertEval("{ b <- c(1,4,5) ; x <- c(2,2) ; b[x==2] <- c(10,11) ; b }"); assertEval("{ b <- c(1,2,5) ; x <- c(2,2,NA) ; b[x==2] <- c(10,11,3) ; b }"); assertEval("{ b <- c(1,2,5) ; x <- as.double(NA) ; attr(x,\"my\") <- 2 ; b[c(1,NA,2)==2] <- x ; b }"); - assertEval(Output.IgnoreWarningContext, "{ b <- c(1,2,5) ; x <- c(2,2,-1) ; b[x==2] <- c(10,11,5) ; b }"); + assertEval("{ b <- c(1,2,5) ; x <- c(2,2,-1) ; b[x==2] <- c(10,11,5) ; b }"); assertEval("{ b <- c(1,2,5) ; b[integer()] <- NULL ; b }"); assertEval("{ b <- c(1,2,5) ; b[c(1)] <- NULL ; b }"); @@ -1769,13 +1786,13 @@ public class TestSimpleVectors extends TestBase { assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,c(TRUE,FALSE,TRUE),5:6) ; f(c(3+4i,5+6i), c(FALSE,TRUE,TRUE), c(NA,1+10i)) }"); assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,c(TRUE,FALSE,TRUE),5:6) ; f(c(TRUE,FALSE), c(FALSE,TRUE,TRUE), c(NA,2L)) }"); assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,TRUE,TRUE), c(NA,FALSE)) }"); - assertEval(Output.IgnoreWarningContext, "{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,TRUE,TRUE), 4:6) }"); + assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,TRUE,TRUE), 4:6) }"); assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,c(TRUE,FALSE,TRUE),5:6) ; f(c(TRUE,TRUE,FALSE), c(FALSE,TRUE,TRUE), c(TRUE,NA)) }"); assertEval(" { f <- function(b, i, v) { b[i] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,TRUE,TRUE), c(NA,FALSE)) }"); - assertEval(Output.IgnoreWarningContext, "{ f <- function(b, i, v) { b[i] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,TRUE,TRUE), 4:6) }"); + assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,TRUE,TRUE), 4:6) }"); assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,NA), 4) }"); assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,NA), 4:5) }"); - assertEval(Output.IgnoreErrorContext, "{ f <- function(b, i, v) { b[[i]] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,NA), 4:5) }"); + assertEval(Output.ImprovedErrorContext, "{ f <- function(b, i, v) { b[[i]] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,NA), 4:5) }"); assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(list(1,2), c(TRUE,FALSE), list(1+2i)) }"); assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(list(1,2), c(TRUE,FALSE), list(1+2i)) ; f(1:2, c(TRUE,FALSE), list(TRUE)) }"); @@ -1787,11 +1804,11 @@ public class TestSimpleVectors extends TestBase { assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(list(1,2), c(TRUE,NA), 10) }"); assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(list(1,2), c(TRUE,NA), c(10,11)) }"); assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; x <- list(1,2) ; z <- x ; f(x, c(TRUE,NA), c(10,11)) }"); - assertEval(Output.IgnoreWarningContext, "{ x <- list(1,2) ; attr(x,\"my\") <- 10; x[c(TRUE,TRUE)] <- c(10,11,12); x }"); - assertEval(Output.IgnoreWarningContext, "{ x <- list(1,0) ; x[as.logical(x)] <- c(10,11); x }"); + assertEval("{ x <- list(1,2) ; attr(x,\"my\") <- 10; x[c(TRUE,TRUE)] <- c(10,11,12); x }"); + assertEval("{ x <- list(1,0) ; x[as.logical(x)] <- c(10,11); x }"); assertEval("{ x <- list(1,0) ; x[is.na(x)] <- c(10,11); x }"); - assertEval(Output.IgnoreWarningContext, "{ x <- list(1,0) ; x[c(TRUE,FALSE)] <- x[2:1] ; x }"); - assertEval(Output.IgnoreWarningContext, "{ x <- list(1,0) ; attr(x,\"my\") <- 20 ; x[c(TRUE,FALSE)] <- c(11,12) ; x }"); + assertEval("{ x <- list(1,0) ; x[c(TRUE,FALSE)] <- x[2:1] ; x }"); + assertEval("{ x <- list(1,0) ; attr(x,\"my\") <- 20 ; x[c(TRUE,FALSE)] <- c(11,12) ; x }"); assertEval("{ x <- list(1,0) ; x[is.na(x)] <- c(10L,11L); x }"); assertEval("{ x <- list(1,0) ; x[c(TRUE,TRUE)] <- c(TRUE,NA); x }"); assertEval("{ x <- list(1,0) ; x[logical()] <- c(TRUE,NA); x }"); @@ -1822,20 +1839,20 @@ public class TestSimpleVectors extends TestBase { assertEval("{ x <- c(1L,2L,3L,4L) ; x[c(TRUE,FALSE)] <- 5:6 ; x }"); assertEval("{ x <- c(1L,2L,3L,4L) ; attr(x,\"my\") <- 0 ; x[c(TRUE,FALSE)] <- 5:6 ; x }"); assertEval("{ x <- c(1L,2L,3L,4L) ; x[is.na(x)] <- 5:6 ; x }"); - assertEval(Output.IgnoreWarningContext, "{ x <- c(1L,2L,3L,4L) ; x[c(TRUE,FALSE)] <- rev(x) ; x }"); + assertEval("{ x <- c(1L,2L,3L,4L) ; x[c(TRUE,FALSE)] <- rev(x) ; x }"); assertEval("{ x <- c(1L,2L) ; x[logical()] <- 3L ; x }"); assertEval("{ b <- c(TRUE,NA,FALSE,TRUE) ; b[c(TRUE,FALSE)] <- c(FALSE,NA) ; b }"); assertEval("{ b <- c(TRUE,NA,FALSE,TRUE) ; b[c(TRUE,FALSE,FALSE)] <- c(FALSE,NA) ; b }"); assertEval("{ b <- c(TRUE,NA,FALSE,TRUE) ; b[c(TRUE,NA)] <- c(FALSE,NA) ; b }"); - assertEval(Output.IgnoreWarningContext, "{ b <- c(TRUE,NA,FALSE) ; b[c(TRUE,TRUE)] <- c(FALSE,NA) ; b }"); + assertEval("{ b <- c(TRUE,NA,FALSE) ; b[c(TRUE,TRUE)] <- c(FALSE,NA) ; b }"); assertEval("{ b <- c(TRUE,NA,FALSE) ; b[c(TRUE,FALSE,TRUE,TRUE)] <- c(FALSE,NA,NA) ; b }"); assertEval("{ b <- c(TRUE,NA,FALSE,TRUE) ; b[c(TRUE,FALSE,TRUE,NA)] <- FALSE ; b }"); assertEval("{ b <- c(TRUE,NA,FALSE,TRUE) ; z <- b ; b[c(TRUE,FALSE,TRUE,NA)] <- FALSE ; b }"); assertEval("{ b <- c(TRUE,NA,FALSE,TRUE) ; attr(b,\"my\") <- 10 ; b[c(TRUE,FALSE,TRUE,NA)] <- FALSE ; b }"); - assertEval(Output.IgnoreWarningContext, "{ b <- c(TRUE,NA,FALSE,TRUE) ; b[c(TRUE,FALSE,TRUE,FALSE)] <- b ; b }"); + assertEval("{ b <- c(TRUE,NA,FALSE,TRUE) ; b[c(TRUE,FALSE,TRUE,FALSE)] <- b ; b }"); assertEval("{ b <- c(TRUE,FALSE,FALSE,TRUE) ; b[b] <- c(TRUE,FALSE) ; b }"); - assertEval(Output.IgnoreWarningContext, "{ f <- function(b,i,v) { b[b] <- b ; b } ; f(c(TRUE,FALSE,FALSE,TRUE)) ; f(1:3) }"); + assertEval("{ f <- function(b,i,v) { b[b] <- b ; b } ; f(c(TRUE,FALSE,FALSE,TRUE)) ; f(1:3) }"); assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(c(TRUE,FALSE,FALSE,TRUE),c(TRUE,FALSE), NA) ; f(1:4, c(TRUE,TRUE), NA) }"); assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(c(TRUE,FALSE,FALSE,TRUE),c(TRUE,FALSE), NA) ; f(c(FALSE,FALSE,TRUE), c(TRUE,TRUE), c(1,2,3)) }"); assertEval("{ b <- c(TRUE,NA,FALSE,TRUE) ; b[logical()] <- c(FALSE,NA) ; b }"); @@ -1846,7 +1863,7 @@ public class TestSimpleVectors extends TestBase { assertEval("{ b <- c(\"a\",\"b\",\"c\") ; b[c(TRUE,FALSE,NA)] <- \"X\" ; b }"); assertEval("{ b <- c(\"a\",\"b\",\"c\") ; b[logical()] <- \"X\" ; b }"); assertEval("{ b <- c(\"a\",\"b\",\"c\") ; b[c(FALSE,NA,NA)] <- c(\"X\",\"y\") ; b }"); - assertEval(Output.IgnoreWarningContext, "{ b <- c(\"a\",\"b\",\"c\") ; b[c(FALSE,TRUE,TRUE)] <- c(\"X\",\"y\",\"z\") ; b }"); + assertEval("{ b <- c(\"a\",\"b\",\"c\") ; b[c(FALSE,TRUE,TRUE)] <- c(\"X\",\"y\",\"z\") ; b }"); assertEval("{ b <- c(\"a\",\"b\",\"c\") ; x <- b ; b[c(FALSE,TRUE,TRUE)] <- c(\"X\",\"z\") ; b } "); assertEval("{ b <- c(\"a\",\"b\",\"c\") ; x <- b ; b[c(FALSE,TRUE,NA)] <- c(\"X\",\"z\") ; b }"); assertEval("{ b <- c(\"a\",\"b\",\"c\") ; b[is.na(b)] <- c(\"X\",\"z\") ; b }"); @@ -2103,12 +2120,12 @@ public class TestSimpleVectors extends TestBase { assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(as.complex(c(13,14)),c(\"\",\"\",\"\"),as.complex(23)) }"); assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(as.complex(c(13,14)),c(\"\",\"\",NA),as.complex(23)) }"); assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(as.raw(c(13,14)),c(\"a\",\"X\",\"a\"),as.raw(23)) }"); - assertEval(Output.IgnoreWarningContext, "{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(c(X=1,a=2),c(\"a\",\"X\",\"a\",\"b\"),list(3,TRUE,FALSE)) }"); + assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(c(X=1,a=2),c(\"a\",\"X\",\"a\",\"b\"),list(3,TRUE,FALSE)) }"); assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(c(X=1,a=2),c(\"X\",\"b\",NA),list(3,TRUE,FALSE)) }"); assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(c(X=1,a=2),c(\"X\",\"b\",NA),as.raw(10)) }"); assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(c(X=1,a=2),c(\"X\",\"b\",NA),as.complex(10)) }"); assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(c(X=1,a=2),c(\"X\",\"b\",NA),1:3) }"); - assertEval(Output.IgnoreWarningContext, "{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1+2i,3:1,4:6) ; f(c(X=1,a=2),c(\"X\",\"b\",NA),c(TRUE,NA)) }"); + assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1+2i,3:1,4:6) ; f(c(X=1,a=2),c(\"X\",\"b\",NA),c(TRUE,NA)) }"); assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1+2i,3:1,4:6) ; f(c(X=1L,a=2L),c(\"X\",\"b\",NA),c(TRUE,NA,FALSE)) }"); assertEval(Output.IgnoreErrorContext, "{ f <- function(b, i, v) { b[[i]] <- v ; b } ; f(1+2i,3:1,4:6) ; f(c(X=1L,a=2L),c(\"X\",\"b\",NA),NULL) }"); assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1+2i,3:1,4:6) ; f(list(X=1L,a=2L),c(\"X\",\"b\",NA),NULL) }"); @@ -2162,10 +2179,10 @@ public class TestSimpleVectors extends TestBase { assertEval("{ x <- NULL; x[c(0,1)] <- c(5); x; }"); assertEval("{ x <- NULL; x[c(0,2)] <- c(5); x; }"); assertEval("{ x <- NULL; x[0] <- c(1,5); x; }"); - assertEval(Output.IgnoreWarningContext, "{ x <- NULL; x[1] <- c(1,5); x; }"); - assertEval(Output.IgnoreWarningContext, "{ x <- NULL; x[c(1,0)] <- c(1,5); x; }"); - assertEval(Output.IgnoreWarningContext, "{ x <- NULL; x[c(0,1)] <- c(1,5); x; }"); - assertEval(Output.IgnoreWarningContext, "{ x <- NULL; x[c(0,2)] <- c(1,5); x; }"); + assertEval("{ x <- NULL; x[1] <- c(1,5); x; }"); + assertEval("{ x <- NULL; x[c(1,0)] <- c(1,5); x; }"); + assertEval("{ x <- NULL; x[c(0,1)] <- c(1,5); x; }"); + assertEval("{ x <- NULL; x[c(0,2)] <- c(1,5); x; }"); assertEval(Output.IgnoreErrorMessage, "{ x <- NULL; x[[c(1,0)]] <- c(1,5); x; }"); assertEval(Output.IgnoreErrorMessage, "{ x <- NULL; x[[c(1,2)]] <- c(1,5); x; }"); @@ -2224,7 +2241,7 @@ public class TestSimpleVectors extends TestBase { assertEval("{ c(\"1L\",\"hello\") %in% 1:10 }"); assertEval("{ (1 + 2i) %in% c(1+10i, 1+4i, 2+2i, 1+2i) }"); assertEval("{ as.logical(-1:1) %in% TRUE }"); - assertEval(Output.IgnoreErrorContext, "{ x <- function(){1} ; x %in% TRUE }"); + assertEval("{ x <- function(){1} ; x %in% TRUE }"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers0.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers0.R index 85acd59a6af3d527c70000c57430fa4fdf38a0e7..d5e10d06e1458c3b71885daa8dd270b1f0d3a11c 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers0.R +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers0.R @@ -1,4 +1,26 @@ -# Ignored +# +# 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. +# + myCondition <- function(message) structure(list(message=message, call=NULL), class=c("myCondition", "condition")) handle_myCondition <- function(e) { @@ -27,6 +49,10 @@ fun1 <- function(s) { NULL } +fun0(quote({ + fun1("first") + fun1("second") +})) fun0({ fun1("first") fun1("second") diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers1.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers1.R index 0345697134cae2a5c8b2e6513b4e799d20987530..2ad7faa555de47457a2ca5d7b7c5897f80e3af23 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers1.R +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers1.R @@ -1,4 +1,26 @@ -# Ignored +# +# 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. +# + cond0 <- function(message) structure(list(message=message, call=NULL), class=c("cond0", "condition")) @@ -38,8 +60,11 @@ fun1 <- function(s) { NULL } +fun0(quote({ + fun1("first") + fun1("second") +})) fun0({ fun1("first") fun1("second") }) - 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 2250149cb2075b762143b4d249ff3d3c5a5ddc6c..0997d603ee8d5b361ee38ac003ee33fa13cb8362 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 @@ -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,14 +22,32 @@ */ package com.oracle.truffle.r.test.library.fastr; +import java.io.IOException; +import java.nio.ByteBuffer; + +import org.junit.Assert; import org.junit.Test; import com.oracle.truffle.api.interop.java.JavaInterop; import com.oracle.truffle.api.vm.PolyglotEngine; +import com.oracle.truffle.r.runtime.conn.SeekableMemoryByteChannel; import com.oracle.truffle.r.test.TestBase; +import java.io.File; +import org.junit.After; public class TestInterop extends TestBase { + private static final SeekableMemoryByteChannel CHANNEL = new SeekableMemoryByteChannel(); + private static final String CHANNEL_NAME = "_fastr_channel0"; + + @After + public void cleanup() { + File f = new File("testScript.R"); + if (f.exists()) { + f.delete(); + } + } + @Test public void testInteropEval() { assertEvalFastR(".fastr.interop.eval('application/x-r', '14 + 2')", "16"); @@ -85,6 +103,7 @@ public class TestInterop extends TestBase { for (TestJavaObject t : TestInterop.testJavaObjects) { builder.globalSymbol(t.name, JavaInterop.asTruffleObject(t.object)); } + builder.globalSymbol(CHANNEL_NAME, JavaInterop.asTruffleObject(CHANNEL)); } @Test @@ -118,5 +137,41 @@ public class TestInterop extends TestBase { assertEvalFastR("v <- .fastr.interop.import('testIntArray'); v", "cat('[1] 1 -5 199\\n" + "attr(,\"is.truffle.object\")\\n" + "[1] TRUE\\n')"); + assertEvalFastR("v <- .fastr.interop.import('testPOJO'); names(v)", "c('intValue', 'longValue', 'charValue', 'shortValue', 'booleanValue', 'stringValue')"); + } + + @Test + public void testChannelConnection() throws IOException { + + final String line0 = "Hello, World!\n"; + final String line1 = "second line\n"; + CHANNEL.write(line0.getBytes()); + CHANNEL.write(line1.getBytes()); + long oldPos = CHANNEL.position(); + CHANNEL.position(0); + assertEvalFastR(String.format("v <- .fastr.interop.import('%s'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); res <- readLines(zz); close(zz); res", + CHANNEL_NAME), + "c('Hello, World!', 'second line')"); + + if (!generatingExpected()) { + // test if FastR consumed the data + Assert.assertEquals(oldPos, CHANNEL.position()); + + // re-open channel + CHANNEL.setOpen(true); + CHANNEL.position(0); + } + + final String response = "hi there"; + assertEvalFastR(String.format("v <- .fastr.interop.import('%s'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); writeLines('%s', zz); close(zz); NULL ", CHANNEL_NAME, response), + "NULL"); + + if (!generatingExpected()) { + ByteBuffer buf = ByteBuffer.allocate(response.length()); + CHANNEL.setOpen(true); + CHANNEL.position(0); + CHANNEL.read(buf); + Assert.assertEquals(response, new String(buf.array())); + } } } 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 new file mode 100644 index 0000000000000000000000000000000000000000..05db254460ed61f551c61cb87e6f2fc1bcc1c1ba --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java @@ -0,0 +1,841 @@ +/* + * 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.test.library.fastr; + +import com.oracle.truffle.r.runtime.RType; +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import org.junit.Assert; + +public class TestJavaInterop extends TestBase { + + private static final String TEST_CLASS = TestClass.class.getName(); + + @Test + public void testToByte() { + assertEvalFastR("v <- .fastr.interop.toByte(1L); v;", "1"); + assertEvalFastR("v <- .fastr.interop.toByte(1.1); v;", "1"); + assertEvalFastR("v <- .fastr.interop.toByte(as.raw(1)); v;", "1"); + assertEvalFastR("v <- .fastr.interop.toByte(1.1); class(v);", "'" + RType.RInteropByte.getName() + "'"); + assertEvalFastR("v <- .fastr.interop.toByte(1.1); typeof(v);", "'" + RType.RInteropByte.getName() + "'"); + assertEvalFastR("v <- .fastr.interop.toByte(" + Byte.MAX_VALUE + "); v;", "" + Byte.MAX_VALUE); + assertEvalFastR("v <- .fastr.interop.toByte(" + Byte.MIN_VALUE + "); v;", "" + Byte.MIN_VALUE); + assertEvalFastR("v <- .fastr.interop.toByte(" + Integer.MAX_VALUE + "); v;", "" + new Integer(Integer.MAX_VALUE).byteValue()); + assertEvalFastR("v <- .fastr.interop.toByte(" + Integer.MIN_VALUE + "); v;", "" + new Integer(Integer.MIN_VALUE).byteValue()); + assertEvalFastR("v <- .fastr.interop.toByte(" + Double.MAX_VALUE + "); v;", "" + new Double(Double.MAX_VALUE).byteValue()); + assertEvalFastR("v <- .fastr.interop.toByte(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).byteValue()); + } + + @Test + public void testToFloat() { + assertEvalFastR("v <- .fastr.interop.toFloat(1L); v;", "1"); + assertEvalFastR("v <- .fastr.interop.toFloat(1.1); v;", "1.1"); + assertEvalFastR("v <- .fastr.interop.toFloat(as.raw(1)); v;", "1"); + assertEvalFastR("v <- .fastr.interop.toFloat(1.1); class(v);", "'" + RType.RInteropFloat.getName() + "'"); + assertEvalFastR("v <- .fastr.interop.toFloat(1.1); typeof(v);", "'" + RType.RInteropFloat.getName() + "'"); + assertEvalFastR("v <- .fastr.interop.toFloat(1L); class(v);", "'" + RType.RInteropFloat.getName() + "'"); + assertEvalFastR("v <- .fastr.interop.toFloat(1L); typeof(v);", "'" + RType.RInteropFloat.getName() + "'"); + assertEvalFastR("v <- .fastr.interop.toFloat(" + Float.MAX_VALUE + "); v;", "" + Float.MAX_VALUE); + assertEvalFastR("v <- .fastr.interop.toFloat(" + Float.MIN_VALUE + "); v;", "" + (double) Float.MIN_VALUE); + assertEvalFastR("v <- .fastr.interop.toFloat(" + Double.MAX_VALUE + "); v;", "Inf"); + assertEvalFastR("v <- .fastr.interop.toFloat(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).floatValue()); + } + + @Test + public void testToLong() { + assertEvalFastR("v <- .fastr.interop.toLong(1L); v;", "1"); + assertEvalFastR("v <- .fastr.interop.toLong(1.1); v;", "1"); + assertEvalFastR("v <- .fastr.interop.toLong(as.raw(1)); v;", "1"); + assertEvalFastR("v <- .fastr.interop.toLong(1.1); class(v);", "'" + RType.RInteropLong.getName() + "'"); + assertEvalFastR("v <- .fastr.interop.toLong(1.1); typeof(v);", "'" + RType.RInteropLong.getName() + "'"); + assertEvalFastR("v <- .fastr.interop.toLong(1L); class(v);", "'" + RType.RInteropLong.getName() + "'"); + assertEvalFastR("v <- .fastr.interop.toLong(1L); typeof(v);", "'" + RType.RInteropLong.getName() + "'"); + assertEvalFastR("v <- .fastr.interop.toLong(" + Integer.MAX_VALUE + "); v;", "" + Integer.MAX_VALUE); + assertEvalFastR("v <- .fastr.interop.toLong(" + Integer.MIN_VALUE + "); v;", "" + Integer.MIN_VALUE); + assertEvalFastR("v <- .fastr.interop.toLong(" + Double.MAX_VALUE + "); v;", "" + new Double(Double.MAX_VALUE).longValue()); + assertEvalFastR("v <- .fastr.interop.toLong(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).longValue()); + } + + @Test + public void testToShort() { + assertEvalFastR("v <- .fastr.interop.toShort(1L); v;", "1"); + assertEvalFastR("v <- .fastr.interop.toShort(1.1); v;", "1"); + assertEvalFastR("v <- .fastr.interop.toShort(as.raw(1)); v;", "1"); + assertEvalFastR("v <- .fastr.interop.toShort(1.1); class(v);", "'" + RType.RInteropShort.getName() + "'"); + assertEvalFastR("v <- .fastr.interop.toShort(1.1); typeof(v);", "'" + RType.RInteropShort.getName() + "'"); + assertEvalFastR("v <- .fastr.interop.toShort(1L); class(v);", "'" + RType.RInteropShort.getName() + "'"); + assertEvalFastR("v <- .fastr.interop.toShort(1L); typeof(v);", "'" + RType.RInteropShort.getName() + "'"); + assertEvalFastR("v <- .fastr.interop.toShort(" + Short.MAX_VALUE + "); v;", "" + Short.MAX_VALUE); + assertEvalFastR("v <- .fastr.interop.toShort(" + Short.MIN_VALUE + "); v;", "" + Short.MIN_VALUE); + assertEvalFastR("v <- .fastr.interop.toShort(" + Integer.MAX_VALUE + "); v;", "" + new Integer(Integer.MAX_VALUE).shortValue()); + assertEvalFastR("v <- .fastr.interop.toShort(" + Integer.MIN_VALUE + "); v;", "" + new Integer(Integer.MIN_VALUE).shortValue()); + assertEvalFastR("v <- .fastr.interop.toShort(" + Double.MAX_VALUE + "); v;", "" + new Double(Double.MAX_VALUE).shortValue()); + assertEvalFastR("v <- .fastr.interop.toShort(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).shortValue()); + } + + @Test + public void testToChar() { + assertEvalFastR("v <- .fastr.interop.toChar(97L); v;", "'a'"); + assertEvalFastR("v <- .fastr.interop.toChar(97.1); v;", "'a'"); + assertEvalFastR("v <- .fastr.interop.toChar(97.1, 1); v;", "cat('Error in .fastr.interop.toChar(97.1, 1) : ', '\n', ' pos argument not allowed with a numeric value', '\n')"); + assertEvalFastR("v <- .fastr.interop.toChar(97L, 1); v;", "cat('Error in .fastr.interop.toChar(97L, 1) : ','\n',' pos argument not allowed with a numeric value', '\n')"); + assertEvalFastR("v <- .fastr.interop.toChar('abc', 1); v;", "'b'"); + assertEvalFastR("v <- .fastr.interop.toChar('abc', 1.1); v;", "'b'"); + assertEvalFastR("v <- .fastr.interop.toChar(97.1); class(v);", "'" + RType.RInteropChar.getName() + "'"); + assertEvalFastR("v <- .fastr.interop.toChar(97.1); typeof(v);", "'" + RType.RInteropChar.getName() + "'"); + assertEvalFastR("v <- .fastr.interop.toChar(97L); class(v);", "'" + RType.RInteropChar.getName() + "'"); + assertEvalFastR("v <- .fastr.interop.toChar(97L); typeof(v);", "'" + RType.RInteropChar.getName() + "'"); + assertEvalFastR("v <- .fastr.interop.toChar('a'); v;", "'a'"); + } + + @Test + public void testToArray() { + assertEvalFastR("a <- .fastr.java.toArray(1L); a;", getRValue(new int[]{1})); + assertEvalFastR("a <- .fastr.java.toArray(c(1L, 2L)); a;", getRValue(new int[]{1, 2})); + assertEvalFastR("a <- .fastr.java.toArray(1L,,T); a;", getRValue(new int[]{1})); + assertEvalFastR("a <- .fastr.java.toArray(c(1L, 2L),,T); a;", getRValue(new int[]{1, 2})); + + assertEvalFastR("a <- .fastr.java.toArray(1.1); a;", getRValue(new double[]{1.1})); + assertEvalFastR("a <- .fastr.java.toArray(c(1.1, 1.2)); a;", getRValue(new double[]{1.1, 1.2})); + assertEvalFastR("a <- .fastr.java.toArray(1.1,,T); a;", getRValue(new double[]{1.1})); + assertEvalFastR("a <- .fastr.java.toArray(c(1.1, 1.2),,T); a;", getRValue(new double[]{1.1, 1.2})); + + assertEvalFastR("a <- .fastr.java.toArray(T); a;", getRValue(new boolean[]{true})); + assertEvalFastR("a <- .fastr.java.toArray(c(T, F)); a;", getRValue(new boolean[]{true, false})); + assertEvalFastR("a <- .fastr.java.toArray(T,,T); a;", getRValue(new boolean[]{true})); + assertEvalFastR("a <- .fastr.java.toArray(c(T, F),,T); a;", getRValue(new boolean[]{true, false})); + + assertEvalFastR("a <- .fastr.java.toArray('a'); a;", getRValue(new String[]{"a"})); + assertEvalFastR("a <- .fastr.java.toArray(c('a', 'b')); a;", getRValue(new String[]{"a", "b"})); + assertEvalFastR("a <- .fastr.java.toArray('a',,T); a;", getRValue(new String[]{"a"})); + assertEvalFastR("a <- .fastr.java.toArray(c('a', 'b'),,T); a;", getRValue(new String[]{"a", "b"})); + + assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1)); a;", getRValue(new short[]{1})); + assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2))); a;", getRValue(new short[]{1, 2})); + assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1),,T); a;", getRValue(new short[]{1})); + assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)),,T); a;", getRValue(new short[]{1, 2})); + + assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'java.lang.Short'); a;", getRValue(new short[]{1})); + assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'java.lang.Short'); a;", getRValue(new short[]{1, 2})); + assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'java.lang.Short', T); a;", getRValue(new short[]{1})); + assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'java.lang.Short', T); a;", getRValue(new short[]{1, 2})); + + assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'int'); a;", getRValue(new int[]{1, 2})); + assertEvalFastR("a <- .fastr.java.toArray(c(1.123, 2.123), 'double'); a;", getRValue(new double[]{1.123, 2.123})); + assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'double'); a;", getRValue(new double[]{1})); + + assertEvalFastR("a <- .fastr.java.toArray(1L); .fastr.java.toArray(a);", getRValue(new int[]{1})); + assertEvalFastR("a <- .fastr.java.toArray(1L); .fastr.java.toArray(a,,T);", getRValue(new int[]{1})); + + assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1)); .fastr.java.toArray(a);", getRValue(new short[]{1})); + + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); to <- .fastr.interop.new(tc); a <- .fastr.java.toArray(to); .fastr.java.isArray(a)", "TRUE"); + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); to <- .fastr.interop.new(tc); a <- .fastr.java.toArray(c(to, to)); .fastr.java.isArray(a)", "TRUE"); + + assertEvalFastR(Ignored.Unimplemented, "a <- .fastr.java.toArray(1L,,F); a;", getRValue(new int[]{1})); + } + + @Test + public void testFromArray() { + testFromArray("fieldStaticBooleanArray", "logical"); + testFromArray("fieldStaticByteArray", "integer"); + testFromArray("fieldStaticCharArray", "character"); + testFromArray("fieldStaticDoubleArray", "double"); + testFromArray("fieldStaticFloatArray", "double"); + testFromArray("fieldStaticIntArray", "integer"); + testFromArray("fieldStaticLongArray", "double"); + testFromArray("fieldStaticShortArray", "integer"); + testFromArray("fieldStaticStringArray", "character"); + + assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$objectArray); is.list(v)", "TRUE"); + testFromArray("objectIntArray", "integer"); + testFromArray("objectDoubleArray", "double"); + assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$mixedTypesArray); is.list(v)", "TRUE"); + + assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$hasNullIntArray); is.list(v)", "TRUE"); + assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[1]", "list(1)"); + assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[2]", "list(NULL)"); + assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[3]", "list(3)"); + } + + public void testFromArray(String field, String type) { + assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$" + field + "); is.vector(v)", "TRUE"); + assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$" + field + "); typeof(v)", getRValue(type)); + } + + @Test + public void testNew() { + assertEvalFastR("tc <- .fastr.java.class('" + Boolean.class.getName() + "'); t <- .fastr.interop.new(tc, TRUE); t", "TRUE"); + assertEvalFastR("tc <- .fastr.java.class('" + Byte.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toByte(1)); t", "1"); + assertEvalFastR("tc <- .fastr.java.class('" + Character.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toChar(97)); t", "'a'"); + assertEvalFastR("tc <- .fastr.java.class('" + Double.class.getName() + "'); t <- .fastr.interop.new(tc, 1.1); t", "1.1"); + assertEvalFastR("tc <- .fastr.java.class('" + Float.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toFloat(1.1)); t", "1.1"); + assertEvalFastR("tc <- .fastr.java.class('" + Integer.class.getName() + "'); t <- .fastr.interop.new(tc, 1L); t", "1"); + assertEvalFastR("tc <- .fastr.java.class('" + Long.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toLong(1)); t", "1"); + assertEvalFastR("tc <- .fastr.java.class('" + Short.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toShort(1)); t", "1"); + assertEvalFastR("tc <- .fastr.java.class('" + String.class.getName() + "'); t <- .fastr.interop.new(tc, 'abc'); t", "'abc'"); + assertEvalFastR("tc <- .fastr.java.class('" + TestNullClass.class.getName() + "'); t <- .fastr.interop.new(tc, NULL); class(t)", "'" + RType.TruffleObject.getName() + "'"); + } + + @Test + public void testCombineInteropTypes() { + assertEvalFastR("class(c(.fastr.interop.toByte(123)))", "'interopt.byte'"); + assertEvalFastR("class(c(.fastr.interop.toByte(123), .fastr.interop.toByte(234)))", "'list'"); + assertEvalFastR("class(c(.fastr.interop.toByte(123), 1))", "'list'"); + assertEvalFastR("class(c(1, .fastr.interop.toByte(123)))", "'list'"); + + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); class(c(t))", "'truffle.object'"); + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t1 <- .fastr.interop.new(tc); class(c(t, t1))", "'list'"); + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); class(c(1, t))", "'list'"); + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); class(c(t, 1))", "'list'"); + } + + @Test + public void testFields() throws IllegalArgumentException, IllegalAccessException { + TestClass t = new TestClass(); + Field[] fields = t.getClass().getDeclaredFields(); + for (Field f : fields) { + String name = f.getName(); + if (name.startsWith("field")) { + testForValue(name, f.get(t)); + } + } + } + + @Test + public void testMethods() throws IllegalAccessException, ClassNotFoundException, IllegalArgumentException, InvocationTargetException { + TestClass t = new TestClass(); + Method[] methods = t.getClass().getDeclaredMethods(); + for (Method m : methods) { + if (m.getParameterCount() == 0) { + String name = m.getName(); + if (name.startsWith("method")) { + testForValue(name + "()", m.invoke(t)); + } + } + } + } + + private void testForValue(String member, Object value) { + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$" + member, getRValue(value)); + } + + @Test + public void testAllTypes() { + getValueForAllTypesMethod("allTypesMethod"); + getValueForAllTypesMethod("allTypesStaticMethod"); + } + + @Test + public void testNonPrimitiveParameter() { + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$equals(t)", "TRUE"); + } + + @Test + public void testClassAsParameter() { + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$classAsArg(tc)", getRValue(TEST_CLASS)); + } + + private void getValueForAllTypesMethod(String method) { + boolean bo = true; + byte bt = Byte.MAX_VALUE; + char c = 'a'; + short sh = Short.MAX_VALUE; + int i = Integer.MAX_VALUE; + long l = Long.MAX_VALUE; + double d = Double.MAX_VALUE; + float f = Float.MAX_VALUE; + String s = "testString"; + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$" + method + "(" + getRValuesAsString(bo, bt, c, sh, i, l, d, f, s) + ")", + getRValue("" + bo + bt + c + sh + i + l + d + f + s)); + } + + @Test + public void testNullParameters() { + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$methodAcceptsOnlyNull(NULL)", ""); + + assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isNull('string')", "java.lang.String"); + assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isNull(1)", "java.lang.Long"); + } + + @Test + public void testOverloaded() { + assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isOverloaded(TRUE)", "boolean"); + assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isOverloaded('string')", String.class.getName()); + // TODO add remaining isOverloaded(...) calls once this is fixed + } + + @Test + public void testArrayReadWrite() { + assertEvalFastR("a <- .fastr.java.toArray(c(1,2,3)); a[1]", "1"); + assertEvalFastR("a <- .fastr.java.toArray(c(1,2,3)); a[[1]]", "1"); + + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldIntArray[1];", "1"); + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldIntArray[[1]];", "1"); + + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[1]", getRValue(new int[]{1, 2, 3})); + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[[1]]", getRValue(new int[]{1, 2, 3})); + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[1,2]", "2"); + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[[1,2]]", "2"); + + assertEvalFastR("a <- .fastr.java.toArray(c(1,2,3)); a[1] <- 123; a[1]", "123"); + assertEvalFastR("a <- .fastr.java.toArray(c(1,2,3)); a[[1]] <- 123; a[[1]]", "123"); + + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldIntArray[1] <- 123L; t$fieldIntArray[1]", "123"); + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldIntArray[[1]] <- 1234L; t$fieldIntArray[[1]]", "1234"); + + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldStringArray[1] <- NULL; t$fieldStringArray[1]", "NULL"); + + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[1,2] <- 1234L; t$int2DimArray[1,2]", "1234"); + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[[1,2]] <- 12345L; t$int2DimArray[[1,2]]", "12345"); + } + + public void testMap() { + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); m <- t$map; m['one']", "'1'"); + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); m <- t$map; m['two']", "'2'"); + + assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); m <- t$map; m['one']<-'11'; m['one']", "'11'"); + + // truffle + assertEvalFastR(Ignored.Unimplemented, "how to put into map?", "'11'"); + } + + @Test + public void testNamesForJavaObject() { + assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClassNoMembers.class.getName() + "'); t <- .fastr.interop.new(tc); names(t)", "NULL"); + assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClassNoPublicMembers.class.getName() + "'); t <- .fastr.interop.new(tc); names(t)", "NULL"); + assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClass.class.getName() + "'); sort(names(tc))", "c('staticField', 'staticMethod')"); + assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClass.class.getName() + "'); names(tc$staticField)", "NULL"); + assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClass.class.getName() + "'); names(tc$staticMethod)", "NULL"); + assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClass.class.getName() + "'); t <- .fastr.interop.new(tc); sort(names(t))", "c('field', 'method', 'staticField', 'staticMethod')"); + assertEvalFastR("cl <- .fastr.java.class('java.util.Collections'); em<-cl$EMPTY_MAP; names(em)", "NULL"); + assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClassMap.class.getName() + "'); t <- .fastr.interop.new(tc); sort(names(t$m()))", "c('one', 'two')"); + } + + private String getRValue(Object value) { + if (value == null) { + return "NULL"; + } + if (value instanceof Boolean) { + return value.toString().toUpperCase(); + } + if (value instanceof Double) { + if (((Double) value) == (((Double) value).intValue())) { + return Integer.toString(((Double) value).intValue()); + } + } + if (value instanceof String) { + return "\"" + value.toString() + "\""; + } + if (value instanceof String) { + return "\"" + value.toString() + "\""; + } + if (value instanceof Character) { + return "\"" + ((Character) value).toString() + "\""; + } + if (value.getClass().isArray()) { + StringBuilder sb = new StringBuilder(); + sb.append("cat('[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)) { + // what the heck? + sb.append(" "); + } + sb.append(getRValue(Array.get(value, i))); + if (i < lenght - 1) { + sb.append(" "); + } + } + sb.append("\\nattr(,\"is.truffle.object\")\\n[1] TRUE\\n')"); + return sb.toString(); + } + return value.toString(); + } + + private String getRValuesAsString(Object... values) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < values.length; i++) { + Object v = values[i]; + sb.append(getRValue(v)); + if (i < values.length - 1) { + sb.append(","); + } + } + return sb.toString(); + } + + public static class TestNamesClass { + public Object field; + public static Object staticField; + + public void method() { + } + + public static void staticMethod() { + } + } + + public static class TestNamesClassNoMembers { + + } + + public static class TestNamesClassNoPublicMembers { + int i; + } + + public static class TestNamesClassMap { + public static Map<String, String> m() { + HashMap<String, String> m = new HashMap<>(); + m.put("one", "1"); + m.put("two", "2"); + return m; + } + } + + public static class TestNullClass { + public TestNullClass(Object o) { + assert o == null; + } + } + + public static class TestClass { + + public static boolean fieldStaticBoolean; + public static byte fieldStaticByte; + public static char fieldStaticChar; + public static short fieldStaticShort; + public static int fieldStaticInteger; + public static long fieldStaticLong; + public static double fieldStaticDouble; + public static float fieldStaticFloat; + + public static Boolean fieldStaticBooleanObject; + public static Byte fieldStaticByteObject; + public static Character fieldStaticCharObject; + public static Short fieldStaticShortObject; + public static Integer fieldStaticIntegerObject; + public static Long fieldStaticLongObject; + public static Double fieldStaticDoubleObject; + public static Float fieldStaticFloatObject; + public static String fieldStaticStringObject; + + public boolean fieldBoolean; + public byte fieldByte; + public char fieldChar; + public short fieldShort; + public int fieldInteger; + public long fieldLong; + public double fieldDouble; + public float fieldFloat; + + public Boolean fieldBooleanObject; + public Byte fieldByteObject; + public Character fieldCharObject; + public Short fieldShortObject; + public Integer fieldIntegerObject; + public Long fieldLongObject; + public Double fieldDoubleObject; + public Float fieldFloatObject; + public String fieldStringObject; + + public static boolean[] fieldStaticBooleanArray; + public static byte[] fieldStaticByteArray; + public static char[] fieldStaticCharArray; + public static double[] fieldStaticDoubleArray; + public static float[] fieldStaticFloatArray; + public static int[] fieldStaticIntArray; + public static long[] fieldStaticLongArray; + public static short[] fieldStaticShortArray; + public static String[] fieldStaticStringArray; + + public boolean[] fieldBooleanArray = fieldStaticBooleanArray; + public byte[] fieldByteArray = fieldStaticByteArray; + public char[] fieldCharArray = fieldStaticCharArray; + public double[] fieldDoubleArray = fieldStaticDoubleArray; + public float[] fieldFloatArray = fieldStaticFloatArray; + public int[] fieldIntArray = fieldStaticIntArray; + public long[] fieldLongArray = fieldStaticLongArray; + public short[] fieldShortArray = fieldStaticShortArray; + public String[] fieldStringArray = fieldStaticStringArray; + + public int[][] int2DimArray; + public Object[] objectArray; + public Object[] objectIntArray; + public Object[] objectDoubleArray; + public Object[] mixedTypesArray; + public Integer[] hasNullIntArray; + + public static Double fieldStaticNaNObject = Double.NaN; + public static double fieldStaticNaN = Double.NaN; + + public static Object fieldStaticNullObject = null; + public Object fieldNullObject = null; + + public Map<String, String> map; + + public TestClass() { + this(true, Byte.MAX_VALUE, 'a', Double.MAX_VALUE, Float.MAX_VALUE, Integer.MAX_VALUE, Long.MAX_VALUE, Short.MAX_VALUE, "a string"); + } + + public TestClass(boolean bo, byte bt, char c, double d, float f, int i, long l, short sh, String st) { + fieldStaticBoolean = bo; + fieldStaticByte = bt; + fieldStaticChar = c; + fieldStaticDouble = d; + fieldStaticFloat = f; + fieldStaticInteger = i; + fieldStaticLong = l; + fieldStaticShort = sh; + fieldStaticStringObject = st; + + fieldStaticBooleanObject = fieldStaticBoolean; + fieldStaticByteObject = fieldStaticByte; + fieldStaticCharObject = fieldStaticChar; + fieldStaticShortObject = fieldStaticShort; + fieldStaticIntegerObject = fieldStaticInteger; + fieldStaticLongObject = fieldStaticLong; + fieldStaticDoubleObject = fieldStaticDouble; + fieldStaticFloatObject = fieldStaticFloat; + + this.fieldBoolean = fieldStaticBoolean; + this.fieldByte = fieldStaticByte; + this.fieldChar = fieldStaticChar; + this.fieldShort = fieldStaticShort; + this.fieldInteger = fieldStaticInteger; + this.fieldLong = fieldStaticLong; + this.fieldDouble = fieldStaticDouble; + this.fieldFloat = fieldStaticFloat; + + this.fieldBooleanObject = fieldBoolean; + this.fieldByteObject = fieldByte; + this.fieldCharObject = fieldChar; + this.fieldShortObject = fieldShort; + this.fieldIntegerObject = fieldInteger; + this.fieldLongObject = fieldLong; + this.fieldDoubleObject = fieldDouble; + this.fieldFloatObject = fieldFloat; + this.fieldStringObject = fieldStaticStringObject; + + fieldStaticBooleanArray = new boolean[]{true, false, true}; + fieldStaticByteArray = new byte[]{1, 2, 3}; + fieldStaticCharArray = new char[]{'a', 'b', 'c'}; + fieldStaticDoubleArray = new double[]{1.1, 2.1, 3.1}; + fieldStaticFloatArray = new float[]{1.1f, 2.1f, 3.1f}; + fieldStaticIntArray = new int[]{1, 2, 3}; + fieldStaticLongArray = new long[]{1, 2, 3}; + fieldStaticShortArray = new short[]{1, 2, 3}; + fieldStaticStringArray = new String[]{"a", "b", "c"}; + + fieldBooleanArray = fieldStaticBooleanArray; + fieldByteArray = fieldStaticByteArray; + fieldCharArray = fieldStaticCharArray; + fieldDoubleArray = fieldStaticDoubleArray; + fieldFloatArray = fieldStaticFloatArray; + fieldIntArray = fieldStaticIntArray; + fieldLongArray = fieldStaticLongArray; + fieldShortArray = fieldStaticShortArray; + fieldStringArray = fieldStaticStringArray; + + int2DimArray = new int[][]{new int[]{1, 2, 3}, new int[]{4, 5, 5}}; + objectArray = new Object[]{new Object(), new Object(), new Object()}; + objectIntArray = new Object[]{1, 2, 3}; + objectDoubleArray = new Object[]{1.1, 2.1, 3.1}; + mixedTypesArray = new Object[]{1, 2.1, 'a'}; + hasNullIntArray = new Integer[]{1, null, 3}; + + map = new HashMap<>(); + map.put("one", "1"); + map.put("two", "2"); + } + + public static boolean methodStaticBoolean() { + return fieldStaticBoolean; + } + + public static byte methodStaticByte() { + return fieldStaticByte; + } + + public static char methodStaticChar() { + return fieldStaticChar; + } + + public static short methodStaticShort() { + return fieldStaticShort; + } + + public static int methodStaticInteger() { + return fieldStaticInteger; + } + + public static long methodStaticLong() { + return fieldStaticLong; + } + + public static double methodStaticDouble() { + return fieldStaticDouble; + } + + public static float methodStaticFloat() { + return fieldStaticFloat; + } + + public static String methodStaticStringObject() { + return fieldStaticStringObject; + } + + public static String[] methodStaticStringArray() { + return fieldStaticStringArray; + } + + public static int[] methodStaticIntArray() { + return fieldStaticIntArray; + } + + public boolean methodBoolean() { + return fieldBoolean; + } + + public byte methodByte() { + return fieldByte; + } + + public char methodChar() { + return fieldChar; + } + + public short methodShort() { + return fieldShort; + } + + public int methodInteger() { + return fieldInteger; + } + + public long methodLong() { + return fieldLong; + } + + public double methodDouble() { + return fieldDouble; + } + + public float methodFloat() { + return fieldFloat; + } + + public String methodStringObject() { + return fieldStringObject; + } + + public String[] methodStringArray() { + return fieldStringArray; + } + + public int[] methodIntArray() { + return fieldIntArray; + } + + public static Boolean methodStaticBooleanObject() { + return fieldStaticBooleanObject; + } + + public static Byte methodStaticByteObject() { + return fieldStaticByteObject; + } + + public static Character methodStaticCharObject() { + return fieldStaticCharObject; + } + + public static Short methodStaticShortObject() { + return fieldStaticShortObject; + } + + public static Integer methodStaticIntegerObject() { + return fieldStaticIntegerObject; + } + + public static Long methodStaticLongObject() { + return fieldStaticLongObject; + } + + public static Double methodStaticDoubleObject() { + return fieldStaticDoubleObject; + } + + public static Float methodStaticFloatObject() { + return fieldStaticFloatObject; + } + + public Boolean methodBooleanObject() { + return fieldBoolean; + } + + public Byte methodByteObject() { + return fieldByteObject; + } + + public Character methodCharObject() { + return fieldCharObject; + } + + public Short methodShortObject() { + return fieldShortObject; + } + + public Integer methodIntegerObject() { + return fieldIntegerObject; + } + + public Long methodLongObject() { + return fieldLongObject; + } + + public Double methodDoubleObject() { + return fieldDoubleObject; + } + + public Float methodFloatObject() { + return fieldFloatObject; + } + + public static Object methodStaticReturnsNull() { + return null; + } + + public Object methodReturnsNull() { + return null; + } + + public void methodAcceptsOnlyNull(Object o) { + Assert.assertNull(o); + } + + public String classAsArg(Class<?> c) { + return c.getName(); + } + + public String allTypesMethod(boolean bo, byte bt, char ch, short sh, int in, long lo, double db, float fl, String st) { + return "" + bo + bt + ch + sh + in + lo + db + fl + st; + } + + public static Object allTypesStaticMethod(boolean bo, byte bt, char ch, short sh, int in, long lo, double db, float fl, String st) { + return "" + bo + bt + ch + sh + in + lo + db + fl + st; + } + + public String isNull(String s) { + return s == null ? String.class.getName() : null; + } + + public String isNull(Long l) { + return l == null ? Long.class.getName() : null; + } + + public boolean equals(TestClass tc) { + return tc == this; + } + + public String isOverloaded(boolean b) { + return "boolean"; + } + + public String isOverloaded(Boolean b) { + return Boolean.class.getName(); + } + + public String isOverloaded(byte b) { + return "byte"; + } + + public String isOverloaded(Byte b) { + return Byte.class.getName(); + } + + public String isOverloaded(char c) { + return "char"; + } + + public String isOverloaded(Character c) { + return Character.class.getName(); + } + + public String isOverloaded(double l) { + return "double"; + } + + public String isOverloaded(Double l) { + return Double.class.getName(); + } + + public String isOverloaded(Float f) { + return Float.class.getName(); + } + + public String isOverloaded(float f) { + return "float"; + } + + public String isOverloaded(int c) { + return "int"; + } + + public String isOverloaded(Integer c) { + return Integer.class.getName(); + } + + public String isOverloaded(long l) { + return "long"; + } + + public String isOverloaded(Long l) { + return Long.class.getName(); + } + + public String isOverloaded(short c) { + return "short"; + } + + public String isOverloaded(Short c) { + return Short.class.getName(); + } + + public String isOverloaded(String s) { + return String.class.getName(); + } + } + + public static class TestArrayClass { + public static TestArrayClass[] testArray = new TestArrayClass[]{new TestArrayClass(), new TestArrayClass(), new TestArrayClass()}; + + } + +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastrGrid/GridColorUtilsTests.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastrGrid/GridColorUtilsTests.java new file mode 100644 index 0000000000000000000000000000000000000000..8e43a26774ed8279b5b93faf526f3e1889520dc0 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastrGrid/GridColorUtilsTests.java @@ -0,0 +1,93 @@ +/* + * 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.fastrGrid; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.oracle.truffle.r.library.fastrGrid.GridColorUtils; +import com.oracle.truffle.r.library.fastrGrid.device.GridColor; +import com.oracle.truffle.r.test.TestBase; + +public class GridColorUtilsTests extends TestBase { + @Test + public void convertFromHex() { + GridColor color = GridColorUtils.gridColorFromString("#FF01FE"); + assertEquals(255, color.getRed()); + assertEquals(1, color.getGreen()); + assertEquals(254, color.getBlue()); + assertEquals(255, color.getAlpha()); + } + + @Test + public void convertFromHexWithAlpha() { + GridColor color = GridColorUtils.gridColorFromString("#FF00FE02"); + assertEquals(255, color.getRed()); + assertEquals(0, color.getGreen()); + assertEquals(254, color.getBlue()); + assertEquals(02, color.getAlpha()); + } + + @Test + public void convertSynonymBlack() { + GridColor black = GridColorUtils.gridColorFromString("black"); + assertEquals(0, black.getRed()); + assertEquals(0, black.getGreen()); + assertEquals(0, black.getBlue()); + assertEquals(255, black.getAlpha()); + } + + @Test + public void convertSynonymUpercaseRed() { + GridColor black = GridColorUtils.gridColorFromString("RED"); + assertEquals(255, black.getRed()); + assertEquals(0, black.getGreen()); + assertEquals(0, black.getBlue()); + assertEquals(255, black.getAlpha()); + } + + @Test + public void convertSynonymLightGreenWithSpace() { + GridColor black = GridColorUtils.gridColorFromString("light green"); + assertEquals(0x90, black.getRed()); + assertEquals(0xee, black.getGreen()); + assertEquals(0x90, black.getBlue()); + assertEquals(255, black.getAlpha()); + } + + @Test + public void convertSynonymLightGreen() { + GridColor black = GridColorUtils.gridColorFromString("light green"); + assertEquals(0x90, black.getRed()); + assertEquals(0xee, black.getGreen()); + assertEquals(0x90, black.getBlue()); + assertEquals(255, black.getAlpha()); + } + + @Test + public void convertSynonymTransparent() { + GridColor transparent = GridColorUtils.gridColorFromString("transparent"); + assertEquals(0, transparent.getAlpha()); + } +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_BinDist.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_BinDist.java index 2d8525a759b25452c31dfe7d7fb5a8f0f0ac8265..d4e60d100df91ac1909b79c858e5560f28ad6944 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_BinDist.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_BinDist.java @@ -37,7 +37,7 @@ public class TestExternal_BinDist extends TestBase { @Test public void testBinDistWrongArgs() { - assertEval(Output.IgnoreWarningContext, ".Call(stats:::C_BinDist, 0, 0, 'string', 3, 5)"); + assertEval(".Call(stats:::C_BinDist, 0, 0, 'string', 3, 5)"); assertEval(".Call(stats:::C_BinDist, c(1,2,3), c(4,5,6), 0, 3, c(NA, 3L))"); assertEval(".Call(stats:::C_BinDist, c(1,2,3), c(4,5,6), 0, 3, -5L)"); } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rbinom.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rbinom.java index 79296c9ac3e58bd59a3d54e33bd25095acc260cc..74edb90098582d5d455debbf565fd715f0b4b791 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rbinom.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rbinom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -32,7 +32,7 @@ public class TestExternal_rbinom extends TestBase { public void testRbinom() { assertEval("set.seed(42); rbinom(10, 10, 0.5)"); assertEval("set.seed(42); rbinom('10', 10, 0.5)"); - assertEval(Output.IgnoreWarningContext, "set.seed(42); rbinom('aa', 10, 0.5)"); + assertEval("set.seed(42); rbinom('aa', 10, 0.5)"); assertEval("set.seed(42); rbinom(10, 2:10, c(0.1, 0.5, 0.9))"); assertEval("set.seed(42); rbinom(1:10, 2:10, c(0.1, 0.5, 0.9))"); assertEval("set.seed(42); rbinom(c(1,2), 11:12, c(0.1, 0.5, 0.9))"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java index e177706ddf6bd78ec67627e6377680d126cf4a5c..69ce1013d43d5ffdd579fdbd037b74d7e8c27e6d 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.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 @@ -51,7 +51,7 @@ public class TestRandGenerationFunctions extends TestBase { assertEval("length(runif(c('a', 'b', 'b', 'd')))"); assertEval("length(runif('3'))"); // wrong size argument - assertEval(Output.IgnoreWarningContext, "runif('hello')"); + assertEval("runif('hello')"); // empty parameters assertEval("runif(2, numeric(), 2)"); assertEval("runif(2, 2, numeric())"); @@ -92,8 +92,14 @@ public class TestRandGenerationFunctions extends TestBase { assertEval("set.seed(12); rmultinom('5', 3.1, c(2, 5, 10))"); // test args validation assertEval("rmultinom(1, 1, -0.15)"); - assertEval(Output.IgnoreErrorContext, Output.IgnoreErrorMessage, "rmultinom('string', 1, 0.15)"); + assertEval("rmultinom('string', 1, 0.15)"); assertEval("rmultinom(1, NA, 0.2)"); assertEval("rmultinom(NA, 1, 0.2)"); } + + @Test + public void testGenerators() { + assertEval("for(gen in c(\"Buggy Kinderman-Ramage\", \"Ahrens-Dieter\", \"Box-Muller\", \"Inversion\", \"Kinderman-Ramage\", \"default\")) { print(paste0(gen, \":\")); RNGkind(NULL,gen); set.seed(42); print(rnorm(30)); }"); + } + } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java index 7d32146ecb76c6ce69082ef78ed32e6e1b54ff2c..0d5d1b076f0246c735de9e0f352deeefa0c75d38 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -26,6 +26,7 @@ import org.junit.Test; import com.oracle.truffle.r.test.TestBase; +// Checkstyle: stop line length check public class TestInteractiveDebug extends TestBase { @Test public void testSimple() { @@ -41,4 +42,50 @@ public class TestInteractiveDebug extends TestBase { public void testNoBracket() { assertEval("f <- function(x) print(x)\ndebug(f)\nf(5)\nx\nn\n"); } + + @Test + public void testLoop() { + assertEval("fun <- function(x) { for(i in seq(x)) cat(i); cat(5) }; debug(fun); fun(3)\n\n\n\n\n\n\n"); + assertEval("fun <- function(x) { for(i in seq(x)) { cat(i) }; cat(5) }; debug(fun); fun(3)\n\n\n\n\n\n\n"); + assertEval("fun <- function(x) { for(i in seq(x)) { cat(i) }; cat(5) }; debug(fun); fun(3)\n\n\n\nf\n\n"); + assertEval("fun <- function(x) { for(j in seq(2)) for(i in seq(x)) cat(i); cat(5) }; debug(fun); fun(3)\n\n\n\n\n\n\n\n\n\n\n\n"); + assertEval("fun <- function(x) { for(j in seq(2)) for(i in seq(x)) cat(i); cat(5) }; debug(fun); fun(3)\n\n\n\nf\nf\n\n"); + } + + @Test + public void testStepInto() { + assertEval("bar <- function(x) { cat(x); cat('\\n') }; foo <- function(x) { cat('foo entry\\n'); bar(x); cat('foo exit\\n') }; debug(foo); foo(3)\n\n\ns\nn\n\n\n\n"); + assertEval("bar <- function(x) { cat(x); cat('\\n') }; foo <- function(x) { cat('foo entry\\n'); bar(x); cat('foo exit\\n') }; debug(foo); foo(3)\n\n\ns\nn\nQ\n"); + assertEval("bar <- function(x) { for(i in seq(x)) print(x) }; foo <- function(x) { cat('foo entry\\n'); bar(x); cat('foo exit\\n') }; debug(foo); foo(5)\n\n\ns\nn\n\n\nf\n\n"); + } + + @Test + public void testPromise() { + // TODO enable test as soon as Truffle support is available + assertEval(Ignored.ImplementationError, "fun <- function(x) { cat({ cat(x); cat('\n') }) }; debug(fun); fun(3)\n\n\n\n\n"); + } + + @Test + public void testNestedDebugging() { + assertEval(Output.IgnoreDebugPath, + "foo <- function(rCode) { eval(parse(text=rCode)); print('foo done') }; debug(foo); foo(\"bar <- function() { print('bar') }; debug(bar); bar()\")\n\n\n\n\n\n"); + assertEval(Output.IgnoreDebugPath, + "foo <- function(rCode) { eval(parse(text=rCode)); print('foo done') }; debug(foo); foo(\"bar <- function() { print('bar') }; debug(bar); bar()\")\n\n\nQ\n"); + } + + @Test + public void testConditionalBreakpoint() { + assertEval("fun <- function(x) { cat('x='); cat(x); cat('\\n') }; trace(fun, quote(if (x > 10) browser())); fun(10)\n; fun(11)\n\n\n\n\n\n"); + } + + @Test + public void testContinue() { + assertEval("fun0 <- function() { print('fun0') }; fun1 <- function() { print('enter fun1'); fun0(); print('exit fun1') }; fun2 <- function() { print('enter fun2'); fun1(); print('exit fun2') }; debug(fun2); fun2()\n\n\ns\nn\n\ns\nc\nc\nc\n"); + } + + @Test + public void testDebugOnce() { + assertEval("fun0 <- function() { print('fun0') }; fun1 <- function() { print('en'); fun0(); fun0(); print('ex') }; debugonce(fun0); fun1()\nc\n"); + assertEval("fun0 <- function() { print('fun0') }; debugonce(fun0); fun0()\nc\n"); + } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTypeConvert.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTypeConvert.java index 2096f7059b4ef0e12eea62f1a015cfda8ef4bb88..ddce0a78c9ad2ed54db3d583a302cd776d8557cb 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTypeConvert.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTypeConvert.java @@ -55,8 +55,7 @@ public class TestTypeConvert extends TestBase { @Test public void testFirstTypeMustBeOfModeTest() { - // UnsupportedSpecializationException: Unexpected values provided for ... - assertEval(Ignored.Unimplemented, "type.convert('NA', 1)"); + assertEval("type.convert('NA', 1)"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/parser/TestParser.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/parser/TestParser.java index c68a0188632178498a05af8e4ae893ddfe2fa08b..9f4562761fefaee3fadc06f56cb08e1c1cb54aa8 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/parser/TestParser.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/parser/TestParser.java @@ -105,6 +105,37 @@ public class TestParser extends TestBase { assertEval(Output.IgnoreErrorMessage, "a <- 1:100; y <- 2; z <- 5; x <- (a[[{y \n * z}]])"); } + @Test + public void testNewLinesInLiterals() { + assertEval("`asdf\nasdf` <- 1; `asdf\nasdf`"); + assertEval("'foo\nbar\baz'"); + assertEval("\"foo\nbar\baz\""); + } + + @Test + public void testEmptySymbols() { + assertEval("names(e)"); + assertEval("e <- quote(b(f=1,foo)); names(e) <- c('','f',''); e"); + assertEval("e <- quote(b(f=1,foo)); names(e) <- c('','',''); e"); + assertEval("f <- function(){ function(``=1) 1 }"); + assertEval("f <- function(){ function(``=1) cat(``=1) }"); + assertEval("f <- function(){ function() cat(``=1) }"); + assertEval("f <- function(){ function() cat(asdf=1) }"); + assertEval("f <- function(){ function(``) cat(asdf=1) }"); + assertEval(Output.IgnoreErrorMessage, "f <- function(){ function('') cat(asdf=1) }"); + assertEval("``(1)"); + assertEval("quote(``(1))"); + assertEval("quote(a$b)"); + assertEval("quote(a$``)"); + assertEval("quote(a$'')"); + assertEval("quote(``:::a)"); + assertEval("quote(a:::a)"); + assertEval("quote(a:::``)"); + assertEval("quote(x <- 1)"); + assertEval(Output.IgnoreErrorMessage, "e <- quote(x <- 1); e[[2]] <- as.symbol(''); "); + assertEval("as.symbol(''))"); + } + @Test public void testLexerError() { // FastR provides a more accurate error message diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackage.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackage.java deleted file mode 100644 index 58fc5690fd0f93b2ae38869dcdea351fc5ad632c..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackage.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * 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 - * 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.rffi; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.oracle.truffle.r.test.TestBase; -import com.oracle.truffle.r.test.TestTrait; -import com.oracle.truffle.r.test.rpackages.TestRPackages; - -public class TestRFFIPackage extends TestRPackages { - - private static final String[] TEST_PACKAGES = new String[]{"testrffi"}; - - @BeforeClass - public static void setupInstallMyTestPackages() { - setupInstallTestPackages(TEST_PACKAGES); - } - - @AfterClass - public static void tearDownUninstallMyTestPackages() { - tearDownUninstallTestPackages(); - } - - /** - * This is somewhat expensive to do per test, but the only alternative is to put all the - * micro-tests in one big test. It might be that this should be switched to an R file-based - * approach as the number of tests increase. - */ - private void assertEvalWithLibWithSetupAndTrait(TestTrait trait, String setup, String test) { - String[] tests = TestBase.template("{ library(\"testrffi\", lib.loc = \"%0\"); " + setup + "x <- " + test + "; detach(\"package:testrffi\", unload=T); x }", - new String[]{TestRPackages.libLoc()}); - if (trait == null) { - assertEval(tests); - } else { - assertEval(trait, tests); - } - } - - private void assertEvalWithLib(String test) { - assertEvalWithLibWithSetupAndTrait(null, "", test); - } - - private void assertEvalWithLibWithSetup(String setup, String test) { - assertEvalWithLibWithSetupAndTrait(null, setup, test); - } - - @Test - public void testRFFI1() { - assertEvalWithLib("rffi.addInt(2L, 3L)"); - } - - @Test - public void testRFFI2() { - assertEvalWithLib("rffi.addDouble(2, 3)"); - } - - @Test - public void testRFFI3() { - assertEvalWithLib("rffi.populateIntVector(5)"); - } - - @Test - public void testRFFI4() { - assertEvalWithLib("rffi.populateLogicalVector(5)"); - } - - @Test - public void testRFFI5() { - assertEvalWithLib("rffi.mkStringFromChar()"); - } - - @Test - public void testRFFI6() { - assertEvalWithLib("rffi.mkStringFromBytes()"); - } - - @Test - public void testRFFI7() { - assertEvalWithLib("rffi.null()"); - } - - @Test - public void testRFFI7E() { - assertEvalWithLib("rffi.null.E()"); - } - - @Test - public void testRFFI7C() { - assertEvalWithLib("rffi.null.C()"); - } - - @Test - public void testRFFI8() { - assertEvalWithLib("rffi.isRString(character(0))"); - } - - @Test - public void testRFFI9() { - assertEvalWithLibWithSetup("a <- c(1L,2L,3L); ", "rffi.iterate_iarray(a)"); - } - - @Test - public void testRFFI10() { - assertEvalWithLibWithSetup("a <- c(1L,2L,3L); ", "rffi.iterate_iptr(a)"); - } - - @Test - public void testRFFI11() { - assertEvalWithLib("rffi.dotCModifiedArguments(c(0,1,2,3))"); - } - - @Test - public void testRFFI12() { - assertEvalWithLib("rffi.dotExternalAccessArgs(1L, 3, c(1,2,3), c('a', 'b'), 'b', TRUE, as.raw(12))"); - } - - @Test - public void testRFFI13() { - assertEvalWithLib("rffi.dotExternalAccessArgs(x=1L, 3, c(1,2,3), y=c('a', 'b'), 'b', TRUE, as.raw(12))"); - } - - @Test - public void testRFFI14() { - assertEvalWithLib("rffi.invoke12()"); - } - - @Test - public void testRFFI15() { - assertEvalWithLib("rffi.TYPEOF(3L)"); - } - - @Test - public void testRFFI16() { - assertEvalWithLib("rffi.isRString(\"hello\")"); - } - - @Test - public void testRFFI17() { - assertEvalWithLib("rffi.isRString(NULL)"); - } - - @Test - public void testRFFI18() { - assertEvalWithLib("rffi.interactive()"); - } - - @Test - public void testRFFI19() { - assertEvalWithLibWithSetup("x <- 1; ", "rffi.findvar(\"x\", globalenv())"); - } - - @Test - public void testRFFI20() { - assertEvalWithLibWithSetup("x <- \"12345\"; ", "rffi.char_length(x)"); - } - - private static final String[] AS_VALUES = new String[]{"1L", "2", "2.2", "T", "integer()", "numeric()", "logical()", "character()", "c(5,6)", "c(2.3, 3.4)", "c(T, F)", - "as.symbol(\"sym\")", "list()"}; - - private static final String[] AS_FUNS = new String[]{"Char", "Integer", "Real", "Logical"}; - - @Test - public void testAsFunctions() { - String[] asCalls = template("x <- append(x, rffi.as%0(%1)); ", AS_FUNS, AS_VALUES); - assertEvalWithLibWithSetupAndTrait(Output.MayIgnoreWarningContext, "x <- list(); ", flatten(asCalls)); - } - - private static final String[] LIST_FUNS = new String[]{"CAR", "CDR"}; - - private static final String[] LIST_VALUES = new String[]{"pairlist(1,2)", "pairlist(x=1L, y=2L)"}; - - @Test - public void testListFunctions() { - String[] calls = template("x <- append(x, rffi.%0(%1)); ", LIST_FUNS, LIST_VALUES); - assertEvalWithLibWithSetupAndTrait(Output.MayIgnoreErrorContext, "x <- list(); ", flatten(calls)); - - } - - private static String flatten(String[] tests) { - StringBuilder sb = new StringBuilder(); - for (String test : tests) { - sb.append(test); - } - return sb.toString(); - } - - private static final String[] LENGTH_VALUES = new String[]{"1", "c(1,2,3)", "list(1,2,3)", "expression(1,2)"}; - - // Checkstyle: stop method name check - @Test - public void TestLENGTH() { - String[] calls = template("x <- append(x, rffi.LENGTH(%0)); ", LENGTH_VALUES); - assertEvalWithLibWithSetupAndTrait(Output.MayIgnoreErrorContext, "x <- list(); ", flatten(calls)); - } - -} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackageCoercions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackageCoercions.java deleted file mode 100644 index 9bff0cf831b4f59dbd62acecb6dbf88ab4c820fc..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackageCoercions.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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 - * 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.rffi; - -import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.CPLXSXP; -import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.EXPRSXP; -import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.INTSXP; -import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.LGLSXP; -import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.NILSXP; -import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.RAWSXP; -import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.REALSXP; -import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.STRSXP; -import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.SYMSXP; -import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.VECSXP; - -import java.util.Arrays; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; -import com.oracle.truffle.r.test.rpackages.TestRPackages; - -public class TestRFFIPackageCoercions extends TestRPackages { - - private static final String[] TEST_PACKAGES = new String[]{"testrffi"}; - - @BeforeClass - public static void setupInstallMyTestPackages() { - setupInstallTestPackages(TEST_PACKAGES); - } - - @AfterClass - public static void tearDownUninstallMyTestPackages() { - tearDownUninstallTestPackages(); - } - - private String addLib(String test) { - return "{ library('testrffi', lib.loc = '" + TestRPackages.libLoc() + "'); x <- " + test + "; detach('package:testrffi', unload=T); x }"; - } - - private static final String[] COERCION_VALUES_FOR_EXPR = new String[]{ - "2", "2.2", "T", "integer()", "numeric()", "logical()", "character()", "c(5,6)", "c(2.3, 3.4)", "c(T, F)", - "list()", "structure(2.2, names='b',dim=c(1,1),myattr='q')", "structure(T, names='c',dim=c(1,1),myattr='q')"}; - - private static final String[] COERCION_VALUES = new String[]{ - "1L", "2", "2.2", "T", "integer()", "numeric()", "logical()", "character()", "c(5,6)", "c(2.3, 3.4)", - "c(T, F)", "list()", "structure(1L,names='a',dim=c(1,1),myattr='q')", "structure(2.2, names='b',dim=c(1,1),myattr='q')", - "structure(T, names='c',dim=c(1,1),myattr='q')", "structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q')"}; - - private static final SEXPTYPE[] COERCION_TYPES = new SEXPTYPE[]{SYMSXP, NILSXP, VECSXP, INTSXP, REALSXP, LGLSXP, STRSXP, CPLXSXP, RAWSXP}; - - private static final String[] COERCION_MODES = Arrays.stream(COERCION_TYPES).map(x -> Integer.toString(x.code)).toArray(n -> new String[n]); - - @Test - public void testCoerceVector() { - String[] tests = template(addLib("rffi.coerceVector(%0, %1)"), COERCION_VALUES, COERCION_MODES); - assertEval(Output.MayIgnoreWarningContext, Output.MayIgnoreErrorContext, tests); - } - - @Test - public void testCoerceVectorToExpression() { - // Note: inconsistency when printing expression(1L) FastR prints just "expression(1)" - String[] tests = template(addLib("rffi.coerceVector(%0, %1)"), COERCION_VALUES_FOR_EXPR, new String[]{Integer.toString(EXPRSXP.code)}); - assertEval(Output.IgnoreErrorMessage, Output.MayIgnoreWarningContext, Output.MayIgnoreErrorContext, tests); - // removes the attributes when its single value, but keeps them when it's a list - assertEval(Ignored.Unimplemented, addLib("rffi.coerceVector(structure(list(1,'x'), names=c('q','w'),dim=c(2,1),myattr='q'), " + EXPRSXP.code + ")")); - } -} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRPackages.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRPackages.java deleted file mode 100644 index 40e4f8d269398f4b187a9d0983b319aa329d6bd0..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRPackages.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * 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 - * 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.rpackages; - -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.Map; - -import org.junit.Assert; - -import com.oracle.truffle.r.runtime.REnvVars; -import com.oracle.truffle.r.runtime.RVersionNumber; -import com.oracle.truffle.r.test.TestBase; - -/** - * Tests related to the loading, etc. of R packages. - * - * THis class should be subclassed by a test that wishes to install one or more packages and - * possibly run additional tests after installation using a pattern of the form - * {@code library(pkg, lib.loc="%0"); sometest()}. Note the use of the {@code %0}, which must be - * satisfied by passing the value of {@code libLoc()}. This is required because the test VM is not - * aware of the test install location so it must be explicitly specified. The use of the {@code %0} - * parameter mechanism also requires the use of {@link TestBase#template} in the test itself. - * - * A subclass must provide {@code @BeforeClass} and {@code @AfterClass}methods that call - * {@link #setupInstallTestPackages} and {@link #tearDownUninstallTestPackages}, respectively, to - * install/remove the specific set of packages relevant to the test. - * - * N.B. The same directory is used when generating expected output with GnuR, and running FastR, to - * keep the {@code lib_loc} argument the same in the test string. So the install is destructive, but - * ok as there is never a clash. - * - * The install directory is cleaned on every call to {@link #setupInstallTestPackages} in case a - * previous install failed to complete {@link #tearDownUninstallTestPackages} successfully. - */ -public abstract class TestRPackages extends TestBase { - - private static final String SYSTEM2_COMMAND = "system2('%s', c('CMD', 'INSTALL', '%s'), env='R_LIBS=%s', stdout=T, stderr=T)"; - - private static String[] installedPackages; - private static Resolver resolver; - private static boolean needsInstall; - - private static final class PackagePath { - /** - * The path containing the package distributions as tar files. - */ - private final Path path; - - private PackagePath(Path path) { - this.path = path; - } - } - - /** - * The path to the install directory. This is fixed across all tests. - */ - private static Path installDir; - - /** - * Map from package name to info on its location. - */ - private static final Map<String, PackagePath> packageMap = new HashMap<>(); - - private static Path installDir() { - if (installDir == null) { - installDir = TestBase.createTestDir("com.oracle.truffle.r.test.rpackages"); - } - return installDir; - } - - protected static String libLoc() { - return installDir().toString(); - } - - private static boolean uninstallPackage(String packageName) { - Path packageDir = installDir().resolve(packageName); - try { - deleteDir(packageDir); - } catch (Throwable e) { - return false; - } - return true; - } - - /** - * Pass a custom subclass of this class to override the actual location of the package tar file. - */ - protected static class Resolver { - Path getPath(String p) { - return testNativePath().resolve(p).resolve("lib").resolve(p + ".tar"); - } - } - - private static Path testNativePath() { - Path p = TestBase.getNativeProjectFile(Paths.get("packages")); - return p; - } - - private static PackagePath getPackagePaths(String pkg, Path path) { - PackagePath result = packageMap.get(pkg); - if (result == null) { - result = new PackagePath(path); - packageMap.put(pkg, result); - } - return result; - } - - private static boolean installPackage(PackagePath packagePath) { - String cmd; - Path binBase; - if (generatingExpected()) { - // use GnuR (internal) - binBase = Paths.get(REnvVars.rHome(), "com.oracle.truffle.r.native", "gnur", RVersionNumber.R_HYPHEN_FULL); - } else { - // use FastR - binBase = Paths.get(REnvVars.rHome()); - } - cmd = binBase.resolve("bin").resolve("R").toString(); - try { - String result = evalInstallPackage(String.format(SYSTEM2_COMMAND, cmd, packagePath.path.toString(), installDir().toString())); - boolean success = result.contains("* DONE ("); - if (!success) { - System.out.println(result); - } - return success; - } catch (Throwable t) { - t.printStackTrace(); - return false; - } - } - - protected static void setupInstallTestPackages(String[] testPackages) { - setupInstallTestPackages(testPackages, new Resolver()); - } - - protected static void setupInstallTestPackages(String[] testPackages, Resolver resolver) { - if (!checkOnly()) { - assert installedPackages == null && TestRPackages.resolver == null : "inconsistent calls to setupInstallTestPackages / tearDownUninstallTestPackages " + installedPackages + " " + resolver; - TestRPackages.installedPackages = testPackages; - TestRPackages.resolver = resolver; - TestRPackages.needsInstall = true; - } - } - - private boolean packagesInstallSuccess = true; - - @Override - public void beforeEval() { - if (needsInstall) { - needsInstall = false; - - TestBase.deleteDir(installDir()); - installDir().toFile().mkdirs(); - System.out.printf(".begin install."); - for (String p : installedPackages) { - // Takes time, provide user feedback - System.out.printf(".pkg: %s.", p); - PackagePath packagePath = getPackagePaths(p, resolver.getPath(p)); - if (!installPackage(packagePath)) { - packagesInstallSuccess = false; - Assert.fail(String.format("package %s failed to install", p)); - } - } - System.out.printf(".end install."); - } - // This makes sure that any consequent tests fail with informative error - Assert.assertTrue("Error during package installation process.", packagesInstallSuccess); - } - - protected static void tearDownUninstallTestPackages() { - if (!checkOnly()) { - assert installedPackages != null && resolver != null : "inconsistent calls to setupInstallTestPackages / tearDownUninstallTestPackages"; - if (!needsInstall) { - for (String p : installedPackages) { - if (!uninstallPackage(p)) { - System.err.println("WARNING: error deleting package: " + p); - } - } - } - installedPackages = null; - resolver = null; - } - } -} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRecommendedPackages.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRecommendedPackages.java deleted file mode 100644 index 04ab1ce911c96d09bfd1a741d56a6625b3bd295f..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRecommendedPackages.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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.test.rpackages; - -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.oracle.truffle.r.test.TestBase; - -/** - * Test the installation of the "recommended" packages that come with GnuR. N.B. There are no - * specific tests beyond install/load as that is handled separately in the package testing - * framework. We are primarily concerned with detecting installation regressions. - * - * N.B. The package 'tgz' files have been copied to the com.oracle.truffle.r.test project output - * directory by the com.oracle.truffle.r.test.native Makefile. to allow them to be packaged into a - * distribution and avoid any dependency on source paths. - * - */ -public class TestRecommendedPackages extends TestRPackages { - // order matters due to dependencies - private static final String[] DEFAULT_PACKAGES = new String[]{"codetools", "MASS", "boot", "class", "cluster", - "lattice", "nnet", "spatial", "Matrix", "survival", "KernSmooth", "foreign", "nlme", - "rpart"}; - private static String[] packages = DEFAULT_PACKAGES; - - /** - * Allows an external agent to ignore certain packages that are known to fail. - */ - public static void ignorePackages(String[] ignoredPackages) { - String[] testPackages = new String[DEFAULT_PACKAGES.length - ignoredPackages.length]; - int k = 0; - outer: for (int i = 0; i < DEFAULT_PACKAGES.length; i++) { - for (int j = 0; j < ignoredPackages.length; j++) { - if (DEFAULT_PACKAGES[i].equals(ignoredPackages[j])) { - continue outer; - } - } - testPackages[k] = DEFAULT_PACKAGES[i]; - k++; - } - packages = testPackages; - } - - @BeforeClass - public static void setupInstallMyTestPackages() { - setupInstallTestPackages(packages, new Resolver() { - @Override - Path getPath(String p) { - return TestBase.getNativeProjectFile(Paths.get("packages")).resolve("recommended").resolve(p + ".tgz"); - } - }); - } - - @AfterClass - public static void tearDownUninstallMyTestPackages() { - tearDownUninstallTestPackages(); - } - - @Test - public void testLoad() { - // This is perhaps redundant as package installation tests whether the package will load. - assertEval(Ignored.OutputFormatting, Context.NonShared, Context.LongTimeout, - TestBase.template("{ library(%1, lib.loc = \"%0\"); detach(\"package:%1\"); }", new String[]{TestRPackages.libLoc()}, packages)); - } -} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestS4TestPackage.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestS4TestPackage.java deleted file mode 100644 index 5843ad45da8f693c315df98ad880aaa92e348ad4..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestS4TestPackage.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.test.rpackages; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.oracle.truffle.r.test.TestBase; - -/** - * Tests related to the loading, etc. of R packages. - */ -public class TestS4TestPackage extends TestRPackages { - - private static final String[] TEST_PACKAGES = new String[]{"tests4"}; - - @BeforeClass - public static void setupInstallMyTestPackages() { - setupInstallTestPackages(TEST_PACKAGES); - } - - @AfterClass - public static void tearDownUninstallMyTestPackages() { - tearDownUninstallTestPackages(); - } - - @Test - public void testS4Load() { - assertEval(TestBase.template("{ library(\"tests4\", lib.loc = \"%0\"); detach(\"package:tests4\"); unloadNamespace(\"tests4\") }", - new String[]{TestRPackages.libLoc()})); - } - - @Test - public void testS4Execute() { - assertEval(TestBase.template( - "{ library(\"tests4\", lib.loc = \"%0\"); r<-print(tests4:::inspect.vehicle(new(\"Car\"), new(\"Inspector\"))); detach(\"package:tests4\"); unloadNamespace(\"tests4\"); r }", - new String[]{TestRPackages.libLoc()})); - assertEval(TestBase.template( - "{ library(\"tests4\", lib.loc = \"%0\"); r<-print(tests4:::inspect.vehicle(new(\"Truck\"), new(\"Inspector\"))); detach(\"package:tests4\"); unloadNamespace(\"tests4\"); r }", - new String[]{TestRPackages.libLoc()})); - assertEval(TestBase.template( - "{ library(\"tests4\", lib.loc = \"%0\"); r<-print(tests4:::inspect.vehicle(new(\"Car\"), new(\"StateInspector\"))); detach(\"package:tests4\"); unloadNamespace(\"tests4\"); r }", - new String[]{TestRPackages.libLoc()})); - assertEval(TestBase.template( - "{ library(\"tests4\", lib.loc = \"%0\"); r<-print(tests4:::inspect.vehicle(new(\"Truck\"), new(\"StateInspector\"))); detach(\"package:tests4\"); unloadNamespace(\"tests4\"); r }", - new String[]{TestRPackages.libLoc()})); - } -} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestVanillaPackage.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestVanillaPackage.java deleted file mode 100644 index 637377fa32eb74183e6864bb203e9d52eb699206..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestVanillaPackage.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 - * 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.rpackages; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.oracle.truffle.r.test.TestBase; - -/** - * Tests related to the loading, etc. of R packages. - */ -public class TestVanillaPackage extends TestRPackages { - - private static final String[] TEST_PACKAGES = new String[]{"vanilla"}; - - @BeforeClass - public static void setupInstallMyTestPackages() { - setupInstallTestPackages(TEST_PACKAGES); - } - - @AfterClass - public static void tearDownUninstallMyTestPackages() { - tearDownUninstallTestPackages(); - } - - @Test - public void testLoadVanilla() { - assertEval(TestBase.template("{ library(\"vanilla\", lib.loc = \"%0\"); r <- vanilla(); detach(\"package:vanilla\"); r }", new String[]{TestRPackages.libLoc()})); - } - - @Test - public void testSimpleFunction() { - assertEval(TestBase.template("{ library(\"vanilla\", lib.loc = \"%0\"); r <- functionTest(c(1,2,3,4,5,6),8:10); detach(\"package:vanilla\"); r }", - new String[]{TestRPackages.libLoc()})); - } - - @Test - public void testQualifiedReplacement() { - assertEval(TestBase.template("{ library(\"vanilla\", lib.loc = \"%0\"); r<-42; vanilla::foo(r)<-7; detach(\"package:vanilla\"); r }", new String[]{TestRPackages.libLoc()})); - } -} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java index 0016b0ebc3e6108885c8411d5277b69fa1d4109f..134b0b01d3aeaa3f7ebe0ea709c59639fd178f46 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java @@ -29,7 +29,10 @@ import static org.junit.Assert.assertTrue; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; import java.util.LinkedList; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import org.junit.After; @@ -38,6 +41,7 @@ import org.junit.Before; import org.junit.Test; import com.oracle.truffle.api.debug.Breakpoint; +import com.oracle.truffle.api.debug.DebugScope; import com.oracle.truffle.api.debug.DebugStackFrame; import com.oracle.truffle.api.debug.DebugValue; import com.oracle.truffle.api.debug.Debugger; @@ -47,13 +51,15 @@ import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.api.vm.PolyglotEngine; import com.oracle.truffle.api.vm.PolyglotEngine.Value; -import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.RCmdOptions.Client; +import com.oracle.truffle.r.runtime.RSource; 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.RContext.ContextKind; -import com.oracle.truffle.r.runtime.data.RPromise.EagerPromiseBase; +import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise; +import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.env.frame.RFrameSlot; public class FastRDebugTest { private Debugger debugger; @@ -160,6 +166,7 @@ public class FastRDebugTest { debuggerSession.suspendNextExecution(); }); + stepInto(1); assertLocation(2, "res = fac(2)"); stepInto(2); assertLocation(9, "nMinusOne = n - 1", @@ -217,7 +224,7 @@ public class FastRDebugTest { stepInto(1); stepOver(3); - assertLocation(6, "i", "i", 4, "n", 15.0, "str", "hello"); + assertLocation(5, "i <- i + 1L", "i", 3, "n", 15.0, "str", "hello"); assertMetaObjects(source, "i", "integer", "n", "double", "str", "character"); stepOut(); performWork(); @@ -228,6 +235,169 @@ public class FastRDebugTest { assertExecutedOK(); } + @Test + public void testScopeFunction() throws Throwable { + final Source srcFunMain = RSource.fromTextInternal("function () {\n" + + " i = 3L\n" + + " n = 15L\n" + + " str = \"hello\"\n" + + " i <- i + 1L\n" + + " ab <<- i\n" + + " i\n" + + "}", RSource.Internal.DEBUGTEST_DEBUG); + final Source source = RSource.fromTextInternal("x <- 10L\n" + + "makeActiveBinding('ab', function(v) { if(missing(v)) x else x <<- v }, .GlobalEnv)\n" + + "main <- " + srcFunMain.getCode() + "\n", + RSource.Internal.DEBUGTEST_DEBUG); + engine.eval(source); + + // @formatter:on + run.addLast(() -> { + assertNull(suspendedEvent); + assertNotNull(debuggerSession); + debuggerSession.suspendNextExecution(); + }); + + assertLocation(1, "main()", "x", 10, "ab", 10, "main", srcFunMain.getCode()); + stepInto(1); + assertLocation(4, "i = 3L"); + stepOver(1); + assertLocation(5, "n = 15L", "i", 3); + stepOver(1); + assertLocation(6, "str = \"hello\"", "i", 3, "n", 15); + stepOver(1); + assertLocation(7, "i <- i + 1L", "i", 3, "n", 15, "str", "hello"); + stepOver(1); + assertLocation(8, "ab <<- i", "i", 4, "n", 15, "str", "hello"); + stepOver(1); + assertScope(9, "i", true, false, "ab", 4, "x", 4); + stepOut(); + assertLocation(1, "main()", "x", 4, "ab", 4, "main", srcFunMain.getCode()); + performWork(); + + final Source evalSource = RSource.fromTextInternal("main()\n", RSource.Internal.DEBUGTEST_EVAL); + engine.eval(evalSource); + + assertExecutedOK(); + } + + @Test + public void testScopePromise() throws Throwable { + final Source source = RSource.fromTextInternal("main <- function(e) {\n" + + " x <- 10L\n" + + " e()\n" + + " x\n" + + "}\n" + + "closure <- function() {\n" + + " x <<- 123L\n" + + " x\n" + + "}\n", + + RSource.Internal.DEBUGTEST_DEBUG); + engine.eval(source); + + // @formatter:on + run.addLast(() -> { + assertNull(suspendedEvent); + assertNotNull(debuggerSession); + debuggerSession.suspendNextExecution(); + }); + + stepOver(1); + stepInto(1); + stepOver(1); + assertScope(3, "e()", false, false, "x", 10); + stepInto(1); + assertLocation(7, "x <<- 123L"); + assertScope(7, "x <<- 123L", true, false, "x", 0); + stepOver(1); + assertScope(8, "x", true, false, "x", 123); + continueExecution(); + performWork(); + + final Source evalSource = RSource.fromTextInternal("x <- 0L\nmain(closure)\n", RSource.Internal.DEBUGTEST_EVAL); + engine.eval(evalSource); + + assertExecutedOK(); + } + + @Test + public void testScopeArguments() throws Throwable { + final Source source = RSource.fromTextInternal("main <- function(a, b, c, d) {\n" + + " x <- 10L\n" + + "}\n" + + "closure <- function() {\n" + + " x <<- 123L\n" + + " x\n" + + "}\n", + + RSource.Internal.DEBUGTEST_DEBUG); + engine.eval(source); + + // @formatter:on + run.addLast(() -> { + assertNull(suspendedEvent); + assertNotNull(debuggerSession); + debuggerSession.suspendNextExecution(); + }); + + assertArguments(1, "main(1, 2, 3, 4)"); + + stepInto(1); + assertArguments(2, "x <- 10L", "a", "b", "c", "d"); + continueExecution(); + performWork(); + + final Source evalSource = RSource.fromTextInternal("main(1, 2, 3, 4)\n", RSource.Internal.DEBUGTEST_EVAL); + engine.eval(evalSource); + + assertExecutedOK(); + } + + @Test + public void testChangedScopeChain() throws Throwable { + final Source source = RSource.fromTextInternal("main <- function(e) {\n" + + " x <- 10L\n" + + " environment(e) <- environment()\n" + + " e()\n" + + " x\n" + + "}\n" + + "closure <- function() {\n" + + " x <<- 123L\n" + + " x\n" + + "}\n", + RSource.Internal.DEBUGTEST_DEBUG); + engine.eval(source); + + // @formatter:on + run.addLast(() -> { + assertNull(suspendedEvent); + assertNotNull(debuggerSession); + debuggerSession.suspendNextExecution(); + }); + + stepOver(1); + stepInto(1); + stepOver(2); + assertScope(4, "e()", false, false, "x", 10); + stepInto(1); + assertLocation(8, "x <<- 123L"); + assertScope(8, "x <<- 123L", true, false, "x", 10); + stepOver(1); + stepOut(); + assertScope(9, "x", false, false, "x", 123); + assertIdentifiers(false, "x", "e"); + stepOut(); + assertScope(9, "x", false, false, "x", 0); + continueExecution(); + performWork(); + + final Source evalSource = RSource.fromTextInternal("x <- 0L\nmain(closure)\n", RSource.Internal.DEBUGTEST_EVAL); + engine.eval(evalSource); + + assertExecutedOK(); + } + private void performWork() { try { if (ex == null && !run.isEmpty()) { @@ -244,7 +414,7 @@ public class FastRDebugTest { } private void stepOut() { - run.addLast(() -> suspendedEvent.prepareStepOut()); + run.addLast(() -> suspendedEvent.prepareStepOut(1)); } private void continueExecution() { @@ -255,40 +425,146 @@ public class FastRDebugTest { run.addLast(() -> suspendedEvent.prepareStepInto(size)); } - private void assertLocation(final int line, final String code, final Object... expectedFrame) { + private void assertIdentifiers(boolean includeAncestors, String... identifiers) { run.addLast(() -> { - assertNotNull(suspendedEvent); - final int currentLine = suspendedEvent.getSourceSection().getStartLine(); - assertEquals(line, currentLine); - final String currentCode = suspendedEvent.getSourceSection().getCode().trim(); - assertEquals(code, currentCode); + final DebugStackFrame frame = suspendedEvent.getTopStackFrame(); + DebugScope scope = frame.getScope(); - final AtomicInteger numFrameVars = new AtomicInteger(0); - frame.forEach(var -> { - numFrameVars.incrementAndGet(); - }); - // There is (self) among the variables, hence substract 1: - assertEquals(expectedFrame.length / 2, numFrameVars.get() - 1); - - for (int i = 0; i < expectedFrame.length; i = i + 2) { - String expectedIdentifier = (String) expectedFrame[i]; - Object expectedValue = expectedFrame[i + 1]; - String expectedValueStr = (expectedValue != null) ? expectedValue.toString() : null; - DebugValue value = frame.getValue(expectedIdentifier); - assertNotNull(value); - String valueStr = value.as(String.class); - assertEquals(expectedValueStr, valueStr); + Set<String> actualIdentifiers = new HashSet<>(); + do { + scope.getDeclaredValues().forEach((x) -> actualIdentifiers.add(x.getName())); + } while (includeAncestors && scope != null && !REnvironment.baseEnv().getName().equals(scope.getName())); + + Set<String> expected = new HashSet<>(); + for (String s : identifiers) { + expected.add(s); } - run.removeFirst().run(); + assertEquals(expected, actualIdentifiers); + + if (!run.isEmpty()) { + run.removeFirst().run(); + } + }); + } + + private void assertLocation(final int line, final String code, final Object... expectedFrame) { + run.addLast(() -> { + try { + assertNotNull(suspendedEvent); + final int currentLine = suspendedEvent.getSourceSection().getStartLine(); + assertEquals(line, currentLine); + final String currentCode = suspendedEvent.getSourceSection().getCode().trim(); + assertEquals(code, currentCode); + compareScope(line, code, false, true, expectedFrame); + } catch (RuntimeException | Error e) { + + final DebugStackFrame frame = suspendedEvent.getTopStackFrame(); + frame.forEach(var -> { + System.out.println(var); + }); + throw e; + } }); } + /** + * Ensure that the scope at a certain program position contains an expected set of key-value + * pairs. + * + * @param line line number + * @param code the code snippet of the program location + * @param includeAncestors Include current scope's ancestors for the identifier lookup. + * @param completeMatch {@code true} if the defined key-value pairs should be the only pairs in + * the scope. + * @param expectedFrame the key-value pairs (e.g. {@code "id0", 1, "id1", "strValue"}) + */ + private void assertScope(final int line, final String code, boolean includeAncestors, boolean completeMatch, final Object... expectedFrame) { + run.addLast(() -> { + try { + compareScope(line, code, includeAncestors, completeMatch, expectedFrame); + } catch (RuntimeException | Error e) { + + final DebugStackFrame frame = suspendedEvent.getTopStackFrame(); + frame.forEach(var -> { + System.out.println(var); + }); + throw e; + } + }); + } + + private void assertArguments(final int line, final String code, final String... expectedArgs) { + run.addLast(() -> { + try { + final DebugStackFrame frame = suspendedEvent.getTopStackFrame(); + + DebugScope scope = frame.getScope(); + + Set<String> actualIdentifiers = new HashSet<>(); + scope.getArguments().forEach((x) -> actualIdentifiers.add(x.getName())); + + assertEquals(line + ": " + code, expectedArgs.length, actualIdentifiers.size()); + + Set<String> expectedIds = new HashSet<>(Arrays.asList(expectedArgs)); + Assert.assertEquals(expectedIds, actualIdentifiers); + + if (!run.isEmpty()) { + run.removeFirst().run(); + } + } catch (RuntimeException | Error e) { + + final DebugStackFrame frame = suspendedEvent.getTopStackFrame(); + frame.forEach(var -> { + System.out.println(var); + }); + throw e; + } + }); + } + + private void compareScope(final int line, final String code, boolean includeAncestors, boolean completeMatch, final Object[] expectedFrame) { + final DebugStackFrame frame = suspendedEvent.getTopStackFrame(); + + final AtomicInteger numFrameVars = new AtomicInteger(0); + frame.forEach(var -> { + // skip synthetic slots + for (RFrameSlot slot : RFrameSlot.values()) { + if (slot.toString().equals(var.getName())) { + return; + } + } + numFrameVars.incrementAndGet(); + }); + if (completeMatch) { + assertEquals(line + ": " + code, expectedFrame.length / 2, numFrameVars.get()); + } + + for (int i = 0; i < expectedFrame.length; i = i + 2) { + String expectedIdentifier = (String) expectedFrame[i]; + Object expectedValue = expectedFrame[i + 1]; + String expectedValueStr = (expectedValue != null) ? expectedValue.toString() : null; + DebugScope scope = frame.getScope(); + DebugValue value; + do { + value = scope.getDeclaredValue(expectedIdentifier); + scope = scope.getParent(); + } while (includeAncestors && value == null && scope != null && !REnvironment.baseEnv().getName().equals(scope.getName())); + assertNotNull("identifier \"" + expectedIdentifier + "\" not found", value); + String valueStr = value.as(String.class); + assertEquals(expectedValueStr, valueStr); + } + + if (!run.isEmpty()) { + run.removeFirst().run(); + } + } + Object getRValue(Object value) { // This will only work in simple cases - if (value instanceof EagerPromiseBase) { - return ((EagerPromiseBase) value).getValue(); + if (value instanceof EagerPromise) { + return ((EagerPromise) value).getValue(); } return value; } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java index 1d79ee857fc804394e83d3bd71097fbca34f8cbd..15ec247889d6c0b2bcdd40c0e010583daff30c58 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java @@ -40,8 +40,7 @@ import com.oracle.truffle.tck.TruffleTCK; public class FastRTckTest extends TruffleTCK { @Test public void testVerifyPresence() { - PolyglotEngine vm = PolyglotEngine.newBuilder().globalSymbol(ContextInfo.GLOBAL_SYMBOL, - null).build(); + PolyglotEngine vm = PolyglotEngine.newBuilder().build(); assertTrue("Our language is present", vm.getLanguages().containsKey("text/x-r")); } @@ -153,6 +152,7 @@ public class FastRTckTest extends TruffleTCK { "builtinFunctionValue <- function() `+`\n" + "builtinFunctionType <- function() 'builtin'\n" + "valueWithSource <- function() intValue\n" + + "objectWithKeyInfoAttributes <- function() { list(rw=1, invocable=function(){ 'invoked' }) }\n" + "for (name in ls()) .fastr.interop.export(name, get(name))\n", RSource.Internal.TCK_INIT ); @@ -506,4 +506,9 @@ public class FastRTckTest extends TruffleTCK { return "valueWithSource"; } + @Override + protected String objectWithKeyInfoAttributes() { + return "objectWithKeyInfoAttributes"; + } + } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java index 85f600102edbe908fc920d4cf39986245b44a250..425f866eadf01fc9692976e6c412df6dfdca39c2 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java @@ -24,19 +24,35 @@ package com.oracle.truffle.r.test.tools; import java.lang.annotation.Annotation; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.Comparator; import com.oracle.truffle.r.nodes.ffi.RFFIUpCallMethod; -import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI; +import com.oracle.truffle.r.runtime.ffi.RFFICstring; /** * Generates the entries for {@link RFFIUpCallMethod}. */ public class RFFIUpCallMethodGenerate { - public static void main(String[] args) { - Method[] methods = UpCallsRFFI.class.getMethods(); + public static void main(String[] args) throws Exception { + String klassName = "com.oracle.truffle.r.runtime.ffi.UpCallsRFFI"; + boolean klassArg = false; + + int i = 0; + while (i < args.length) { + String arg = args[i]; + if (arg.equals("--class")) { + i++; + klassName = args[i]; + klassArg = true; + } + i++; + } + + Class<?> klass = Class.forName(klassName); + Method[] methods = klassArg ? klass.getDeclaredMethods() : klass.getMethods(); Arrays.sort(methods, new Comparator<Method>() { @@ -46,8 +62,11 @@ public class RFFIUpCallMethodGenerate { } }); - for (int i = 0; i < methods.length; i++) { + for (i = 0; i < methods.length; i++) { Method m = methods[i]; + if (klassArg && (Modifier.isStatic(m.getModifiers()))) { + continue; + } String sig = getNFISignature(m); System.out.printf("%s(\"%s\")%s%n", m.getName(), sig, i == methods.length - 1 ? ";" : ","); } @@ -73,18 +92,38 @@ public class RFFIUpCallMethodGenerate { return sb.toString(); } - static String nfiParamName(Class<?> paramType, Annotation[] annotation) { + static String nfiParamName(Class<?> paramType, Annotation[] annotations) { String paramName = paramType.getSimpleName(); - Class<?> klass = annotation.length == 0 ? null : annotation[0].annotationType(); + RFFICstring rffiCstring = null; + if (annotations.length > 0) { + for (Annotation annotation : annotations) { + if (annotation instanceof RFFICstring) { + rffiCstring = (RFFICstring) annotation; + break; + } + } + } switch (paramName) { case "Object": - return klass == null ? "object" : "pointer"; + if (rffiCstring == null) { + return "object"; + } else { + return rffiCstring.convert() ? "string" : "pointer"; + } + case "char": + return "uint8"; case "int": return "sint32"; case "double": return "double"; case "void": return "void"; + case "int[]": + return "[sint32]"; + case "double[]": + return "[double]"; + case "byte[]": + return "[uint8]"; default: return "object"; } diff --git a/documentation/dev/casts.md b/documentation/dev/casts.md index a34394385304d479aeb153c6bb332ee12de3a67f..0ec57e6e9fe3c269b5ac9e5a4ad8a85666672043 100644 --- a/documentation/dev/casts.md +++ b/documentation/dev/casts.md @@ -1,8 +1,8 @@ ## Introduction -Cast Pipelines (CP) are used to convert, validate and analyse input arguments of FastR builtins. The aim is to make the code in builtin specializations cleaner by relieving them from the burden of repeated argument handling that often leads to duplicate boilerplate code. Ideally, all argument handling code should be concentrated in a single method in a builtin. However, in certain situations, e.g. when a validation code evaluates more than one argument, the validation code cannot be moved to that single method. +Cast Pipelines (CP) are used to convert, validate and analyze input arguments of FastR builtins. The aim is to make the code in builtin specializations cleaner by relieving them from the burden of repeated argument handling that often leads to duplicate boilerplate code. Besides that, the declarative nature of CP allows for static analysis of pipelines, which is used to diagnose builtins by a special tool (mx rbdiag). -CP provides an API through which a _pipeline_ can be constructed declaratively for each builtin argument. This pipeline consists of one or more steps representing specific operations with the given argument. Because of the declarative character of the argument processing pipelines it is possible to retrieve additional information from the pipelines, which may be further used in tests or code analysis. For instance, each pipeline provides a set of output types, which may be used for coverage analysis of the builtin specializations, i.e. to check if no specialization is missing or unused. Also, in many cases it is possible to determine specific argument values from pipelines, such as default values, limit values of value intervals, and allowed or forbidden values (i.e. corner-case argument values). These specific values may be collected as argument samples and used to create automated tests of builtins. The argument samples are naturally divided into the positive and negative sample sets. The positive samples can be used to test the builtin's functionality and compare the result with the result of the builtin's GnuR counterpart. On the the other hand, the negative samples, which are assumed to cause an error in the FastR builtin, can be used to determine if the GnuR version fails too and produces the same error; if not, the pipeline must be redesigned to reflect the original. +CP provides an API through which a _pipeline_ can be constructed declaratively for each builtin argument. This pipeline consists of one or more steps representing specific operations with the given argument. Because of the declarative character of the argument processing pipelines it is possible to retrieve additional information from the pipelines, which may be further used in tests or code analysis. For instance, each pipeline provides a set of output types, which may be used for coverage analysis of the builtin specializations, i.e. to check if no specialization is missing or unused. Also, in many cases it is possible to determine specific argument values from pipelines, such as default values, limit values of value intervals, and allowed or forbidden values (a.k.a. corner-case argument values). These specific values may be collected as argument samples and used to create automated tests of builtins (a.k.a. chimney-sweeping). The argument samples are naturally divided into the positive and negative sample sets. The positive samples can be used to test the builtin's functionality and compare the result with the result of the builtin's GnuR counterpart. On the the other hand, the negative samples, which are assumed to cause an error in the FastR builtin, can be used to determine if the GnuR version fails too and produces the same error; if not, the pipeline must be redesigned to reflect the original. The following sections deal with the description of the CP API and with some implementation details. @@ -10,13 +10,15 @@ The following sections deal with the description of the CP API and with some imp ### Basics: usage in builtins -CP API is an extension of the `CastBuilder` class, whose instance is passed as the argument of the `createCasts` method that can be overridden in a builtin class to define custom argument conversions for the builtin. The body of the `createCasts` method is the place where the cast pipelines are constructed for every argument of the builtin requiring some conversion or validation, as shown in the following listing. +CP API is available through the `NodeWithArgumentCasts.Casts` class. For every builtin there is one instance of that class instantiated in the static block of the builtin class. The static block is also the place where the cast pipelines are constructed for every argument of the builtin requiring some conversion or validation, as shown in the following listing: ```java - @Override - protected void createCasts(CastBuilder casts) { + // in MyBuiltin class + static { + Casts casts = new Casts(MyBuiltin.class); + casts.arg("X").mustBe(numericValue(), RError.Message.X_NUMERIC); - + casts.arg("m").asIntegerVector(). findFirst(). notNA(); @@ -31,15 +33,24 @@ CP API is an extension of the `CastBuilder` class, whose instance is passed as t } ``` -The CP API part for the pipeline construction is designed in the fluent-builder style. A new pipeline for an argument is initialized by calling the `arg` method on the `CastBuilder` instance. The `arg` method accepts either the index of the argument or the name of the argument, while the latter case is preffered. Following the `arg` method is a series of steps, each inserting a special Truffle node (`CastNode`) into the cast pipeline of the argument. The flow of a pipeline can be divided into four phases: _pre-initial_, _initial_, _coerced_ and _head_, while the last three are optional and each phase may consist of zero or more steps. +In case the builtin does not declare any cast pipeline from any reason, it should declare this fact as follows: + +```java + // in MyBuiltin class + static { + Casts.noCasts(MyBuiltin.class); + } +``` + +The CP API for the pipeline construction is designed in the fluent-builder style. A new pipeline for an argument is initialized by calling the `arg` method on the `Casts` instance. The `arg` method accepts either the index of the argument or the name of the argument, while the latter case is preffered. Following the `arg` method is a series of steps, in which each step inserts, behind the scenes, a special Truffle nodes (`CastNode`) into the cast pipeline. The flow of a pipeline can be divided into four phases: _pre-initial_, _initial_, _coerced_ and _head_, while the last three are optional and each phase may consist of zero or more steps. -In the **pre-initial** phase one can configure the overall behavior of the pipeline. Currently, only the default handling of `RNull` and `RMissing` values can be overridden (the default behavior is explained below). The pipeline can be configured using `PreinitialPhaseBuilder.conf(Consumer)` or any other method of the `PreinitialPhaseBuilder` class, e.g. `PreinitialPhaseBuilder.allowNull()`. +In the **pre-initial** phase, in addition to the **initial** phase, one can configure the overall properties and behaviour of the pipeline (see `PipelineConfigBuilder`). The pipeline can be configured using the `conf(Consumer)` step (declared in `PreinitialPhaseBuilder`). -An argument enters the **initial** phase as a generic object, which may be subjected to various assertions and conversions. The argument may, but may not, exit the initial phase as an instance of a specific type. The pipeline declared in the following listing specifies the default error of the pipeline and inserts one assertion node checking whether the argument is a non-null string. The argument exits this pipeline as a string represented by the `RAbstractStringVector` class. If any of the two conditions fails, the default error is raised. +The **initial** and **pre-initial** phases handle the input argument as a generic object, which may be subjected to various assertions and conversions. The argument may, but may not, exit the initial phase as an instance of a specific type. The pipeline declared in the following listing specifies the default error of the pipeline and inserts one assertion node checking whether the argument is a non-null string. The argument exits this pipeline as a string represented by the `RAbstractStringVector` class. If any of the two conditions fails, the default error is raised. ```java casts.arg("m").defaultError(RError.Message.MUST_BE_STRING, "msg1"). - mustBe(notNull().and(stringValue())); + mustBe(nullValue().not().and(stringValue())); ``` The argument enters the **coerced** phase after having been processed by a node inserted by one of the `as_X_Vector` pipeline steps, where `X` is the type of the resulting vector. The input type of the argument corresponds to the used `as_X_Vector` step. The following example illustrates a pipeline, where the initial phase consists of one step (`asIntegerVector`) and the coerced phase has no step. @@ -58,15 +69,15 @@ The next listing shows a pipeline having two steps belonging to the initial phas findFirst(); ``` -The `singleElement()` condition requires that the string vector contain exactly one element. The `findFirst()` step retrieves the first element (the head) while exiting the coerced phase and entering the head phase. +The `singleElement()` condition requires that the string vector contain exactly one element. The `findFirst()` step retrieves the first element of the vector argument (the head) while exiting the coerced phase and entering the head phase. -In the **head** phase, the argument value corresponds to the first element of the vector processed in the preceding coerced phase and may be handled basically by the same steps as in the initial phase, except the `as_X_Vector` steps. The head phase in the following example consists of two steps - `mustBe(notLogicalNA())` and `map(toBoolean())` - where the former asserts that the head of the logical vector argument must not be `NA` and the latter converts the logical value from the vector's head to the corresponding `boolean` value. The `findFirst` step in the coerced phase picks the head of the vector or returns the `RRuntime.LOGICAL_FALSE` in case the vector is empty. +In the **head** phase, the argument value corresponds to the first element of the vector processed in the preceding coerced phase and may be handled basically by the same steps as in the initial phase, except the `as_X_Vector` steps. The head phase in the following example consists of two steps - `mustBe(logicalNA().not())` and `map(toBoolean())` - where the former asserts that the head of the logical vector argument must not be `NA` and the latter converts the logical value from the vector's head to the corresponding `boolean` value. The `findFirst` step in the coerced phase picks the head of the vector or returns the `RRuntime.LOGICAL_FALSE` in case the vector is empty. ```java casts.arg("na.encode"). asLogicalVector(). findFirst(RRuntime.LOGICAL_FALSE). - mustBe(notLogicalNA()). + mustBe(logicalNA().not()). map(toBoolean()); ``` @@ -80,6 +91,14 @@ import com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBu CastNode myCastNode = newCastBuilder().asStringVector().findFirst("default").buildCastNode(); ``` +### Class `Predef` + +The `CastBuilder.Predef` class defines the `cast pipelines` DSL. By importing statically its content, all language elements, such as filters and mappers, become available. + +```java +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.* +``` + ### Steps The following subsections are dealing with the specific types of pipeline steps. @@ -92,16 +111,12 @@ There are two steps that actually insert no node into the pipeline. The `default There are two modal steps - `mustBe` and `shouldBe` - that establish assertions on the argument value. If the assertion fails, the former raises an error, while the latter outputs a warning. If no message is specified, the default one is used. These steps may be used in all phases. -The assertion conditions are passed as the first argument of those steps and must match the context argument type, which is `java.lang.Object` initially and may be made more specific further in the pipeline by certain steps, among which is also the `mustBe` one. The conditions are objects implementing the `ArgumentFilter<T, R extends T>` interface. Under normal circumstances, the user is not supposed to implement custom conditions. Instead, there is a set of predefined conditions in the `CastBuilder.Predef` class, which should contain all conditions occuring in the original GnuR code, although some may be missing. - -```java -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.* -``` +The assertion conditions are passed as the first argument of those steps and must match the context argument type, which is `java.lang.Object` initially and may be made more specific further in the pipeline by certain steps, among which is also the `mustBe` one. The conditions are objects implementing the `ArgumentFilter<T, R extends T>` interface. Under normal circumstances, the user is not supposed to implement custom conditions. Instead, there is a set of predefined conditions in the `CastBuilder.Predef` class, which should contain all conditions occuring in the original GnuR code, although some may be missing, while others may be added. The `ArgumentFilter<T, R extends T>` contains the logical operators `and`, `or` and `not`, which allows constructing more complex assertions from the elementary building blocks, as shown in the following listing. The expression asserts that the argument value must be a non-null string or logical value. ```java -casts.arg("msg1").mustBe(notNull().and(stringValue().or(logicalValue()))); +casts.arg("msg1").mustBe(nullValue().not().and(stringValue().or(logicalValue()))); ``` The `mustBe` step changes the context argument type of the argument in the following steps accordingly to the used filter expression. For example, in the following pipeline the `mustBe` step asserts that the argument must be a vector. This assertion narrows the context argument type in the following steps to `RAbstractVector`. Therefore, the conditions requiring a vector as the input value, such as `size`, may be used in the subsequent `shouldBe` step. @@ -112,18 +127,30 @@ casts.arg("x").mustBe(abstractVectorValue()).shouldBe(size(2)); #### Mapping Steps -The mapping steps allow converting the argument from one type to another using the so-called mappers passed as the argument of those steps. There are two mapping steps: `map` and `mapIf`. The former always converts the argument using the mapper object passed as the first argument, while the latter converts the argument only if the condition passed as the first argument is `true`. The mapper object implements the `ArgumentMapper<S, R>` interface, nevertheless, just as in the case of the filter conditions, the user is not expected to implement custom ones, since the `CastBuilder.Predef` class should contain all necessary mappers. +The mapping steps allow converting the argument from one type to another using the so-called mappers passed as the argument of those steps. There are three mapping steps: `map`, `mapIf` and `returnIf`. The first one always converts the argument using the mapper object passed as the first argument, while the second converts the argument only if the condition passed as the first argument is `true`. Both converted and non-converted arguments then proceed to the next step in the pipeline. The third one works as the second one, except that the converted value exits the pipeline without further processing. +Both `mapIf` and `returnIf` allow specifying the false mapping branch too. Interestingly, the `returnIf` can be specified with no mapping branch at all, which results in exiting the pipeline with the input argument if it matches the filter condition (it is equivalent to the true branch being the identity mapper). +The following pipeling returns NULL immediately without propagating it further in the pipeline: + +```java +casts.arg("x").returnIf(nullValue()).asIntegerVector().findFirst(); +``` + +The mapper object implements the `ArgumentMapper<S, R>` interface, nevertheless, just as in the case of the filter conditions, the user is not expected to implement custom ones, since the `CastBuilder.Predef` class should contain all necessary mappers. The mapping steps may be used in all phases except the coerced phase, for the time being. The signatures of the mapping steps are: ```java -map(ArgumentMapper<T, S> mapFn) -mapIf(ArgumentFilter<? super T, ? extends S> argFilter, ArgumentMapper<S, R> mapFn) +map(Mapper<T, S> mapFn) +mapIf(Filter<? super T, ? extends S> argFilter, Mapper<S, R> trueBranchMapper) +mapIf(Filter<? super T, ? extends S> argFilter, Mapper<S, R> trueBranchMapper, Mapper<S, R> falseBranchMapper) +returnIf(Filter<? super T, ? extends S> argFilter) +returnIf(Filter<? super T, ? extends S> argFilter, Mapper<S, R> trueBranchMapper) +returnIf(Filter<? super T, ? extends S> argFilter, Mapper<S, R> trueBranchMapper, Mapper<S, R> falseBranchMapper) ``` -A usage of the unconditional is illustrated in the following listing, where a logical value is mapped to a boolean value using the `toBoolean()` mapper. Since the unconditional mapping changes the context argument type according to the output type of the used mapper, it is possible to append the `shouldBe` modal step with the `trueValue()` filter requiring a boolean value on its input. +A usage of the unconditional map step is illustrated in the following listing, where a logical value is mapped to a boolean value using the `toBoolean()` mapper. Since the unconditional mapping changes the context argument type according to the output type of the used mapper, it is possible to append the `shouldBe` modal step with the `trueValue()` filter requiring a boolean value on its input. ```java casts.arg("na.rm"). @@ -133,7 +160,7 @@ A usage of the unconditional is illustrated in the following listing, where a lo shouldBe(trueValue()); ``` -In the following pipeline **only** null values are converted to the empty string in the initial phase. In contrast to the unconditional mapping, the conditional mapping does not change the context type. +In the following pipeline **only** null values are converted to the empty string in the initial phase. In contrast to the unconditional mapping, the conditional mapping reduces the context type to `Object`. ```java casts.arg("quote").mapIf(nullValue(), constant("")); @@ -143,11 +170,13 @@ casts.arg("quote").mapIf(nullValue(), constant("")); The vector coercion steps coerce the input argument value to the specified vector type. These steps can be used in the initial phase only. There are the following steps available: -* `asIntegerVector()`: coerces the input value to `RAbstractIntVector` -* `asDoubleVector()`: coerces the input value to `RAbstractDoubleVector` -* `asLogicalVector()`: coerces the input value to `RAbstractLogicalVector` -* `asStringVector()`: coerces the input value to `RAbstractStringVector` -* `asVector()`: coerces the input value to `RAbstractVector` +* `asIntegerVector()`: coerces the input value to `RAbstractIntVector` (see `CastIntegerNode`) +* `asDoubleVector()`: coerces the input value to `RAbstractDoubleVector` (see `CastDoubleNode`) +* `asLogicalVector()`: coerces the input value to `RAbstractLogicalVector` (see `CastLogicalNode`) +* `asStringVector()`: coerces the input value to `RAbstractStringVector` (see `CastStringNode`) +* `asComplexVector()`: coerces the input value to `RAbstractComplexVector` (see `CastComplexNode`) +* `asRawVector()`: coerces the input value to `RAbstractRawVector` (see `CastRawNode`) +* `asVector()`: coerces the input value to `RAbstractVector` (see `CastToVectorNode`) All these steps terminate the initial phase and start the coerced phase. @@ -162,9 +191,10 @@ findFirst() findFirst(RError.Message message, Object... messageArgs) <E>findFirst(E defaultValue) <E>findFirst(E defaultValue, RError.Message message, Object... messageArgs) +findFirstOrNull() ``` -The first variant raises the default error of the pipeline as long as the vector is empty, the second variant throws the error specified in its arguments, the third one returns the default value instead of raising an error and the fourth one returns the default value and prints the warning specified in its arguments. +The first variant raises the default error of the pipeline as long as the vector is empty, the second variant throws the error specified in its arguments, the third one returns the default value instead of raising an error and the fourth one returns the default value and prints the warning specified in its arguments. The fifth one returns NULL if the vector argument is empty. #### notNA @@ -177,20 +207,20 @@ notNA(T naReplacement) notNA(T naReplacement, RError.Message message, Object... messageArgs) ``` -Analogously to the findFirst step, the no-arg version throws the default error if the argument value is NA, while the second version throws the specified error. The next two versions return the `naReplacement` value, instead of raising an exception, while the last version prints the specified warning. +Analogously to the findFirst step, the no-arg version throws the default error if the argument value is an NA, while the second version throws the specified error. The next two versions return the `naReplacement` value, instead of raising an exception, while the last version prints the specified warning. The notNA step does not change the context argument type. ### Handling of RNull and RMissing values -By default, `RNull` and `RMissing` argument values are sent to the pipeline. While most of the pipeline cast nodes ignore those values and let them pass through, there are some nodes that may perform some transformation of those values. For example, the `FindFirstNode` node replaces both `RNull` and `RMissing` by the replacement values specified in the corresponding `findFirst(repl)` pipeline step. Also the `CastToVectorNode` coercion node replaces those values by an empty list provided that the `isPreserveNonVector` flag is set. +By default, `RNull` and `RMissing` argument values __are sent to the pipeline__. While most of the pipeline cast nodes ignore those values and let them pass through, there are some nodes that may perform some transformation of those values. For example, the `FindFirstNode` node replaces both `RNull` and `RMissing` by the replacement values specified in the corresponding `findFirst(repl)` pipeline step. Also the `CastToVectorNode` coercion node replaces those values by an empty list provided that the `isPreserveNonVector` flag is set (i.e. `asVector(true)`) . The following list summarizes the behavior of a couple of pipeline steps with regard to the special values: -* `as<TYPE>()` coercions: RNull/RMissing passing through +* `as<TYPE>()` coercions: RNull/RMissing pass through, except `asVector(true)`, which converts null to the empty list * `findFirst`: RNull/RMissing treated as an empty vector, i.e. if the default value is specified it is used as a replacement for the special value, otherwise an error is raised. -* `notNA`: RNull/RMissing passing through -* `mustBe`, `shouldBe`: the filter condition determines whether RNull/RMissing is let through, e.g. `mustBe(stringValue())` blocks NULL since it is obviously not a string value. On the other hand, `shouldBe(stringValue())` lets the NULL through. +* `notNA`: RNull/RMissing pass through +* `mustBe`, `shouldBe`: the filter condition determines whether RNull/RMissing is let through, e.g. `mustBe(stringValue())` blocks NULL since it is obviously not a string value. On the other hand, `shouldBe(stringValue())` lets the NULL through. On the other hand, `mustBe(nullValue().or(stringValue))` lets NULL pass. * `mapIf`: the condition behaves accordingly to the used filter (in the 1st parameter). For example, step `mapIf(stringValue(), constant(0), constant(1))` maps NULL to 1. The following cast pipeline examples aim to elucidate the behavior concerning the special values. @@ -213,16 +243,13 @@ Both NULL and MISSING pass through the pipeline: cb.arg("x").mustBe(stringValue().not()); ``` -NULL does not pass through the pipeline. MISSING passes through. - -```java - cb.arg("x").mustNotBeNull().mustBe(stringValue().not()); -``` - -The same as above: +NULL does not pass through the pipeline. MISSING passes through. All the following pipelines are equivalent: ```java + cb.arg("x").mustBe(nullValue().not()).mustBe(stringValue().not()); cb.arg("x").mustBe(nullValue().not().and(stringValue().not())); + cb.arg("x").mustBe((nullValue().or(stringValue())).not()); + cb.arg("x").mustNotBeNull().mustBe(stringValue().not()); ``` Neither NULL nor MISSING pass through the pipeline: @@ -231,20 +258,6 @@ Neither NULL nor MISSING pass through the pipeline: cb.arg("x").asStringVector().mustBe(singleElement()); ``` -#### Overriding the default behavior - -A cast pipeline can be configured not to send `RNull` and/or `RMissing` to the cast nodes forming the cast pipeline. Then those values either bypass the pipeline, being eventually transformed to some constant, or an error is raised. One can use the following steps in the pre-initial phase to override the default behavior: - -* `allowNull` - RNull bypasses the pipeline -* `mustNotBeNull(errorMsg)` - the error with errorMsg is raised when the input argument is `RNull` -* `mapNull(mapper)` - `RNull` is transformed using the mapper. The `RNull` replacement bypasses the pipeline. - -Analogous methods exist for `RMissing`. - -#### Optimizing the default behavior - -The above-mentioned overriding configurations may also be applied behind-the-scenes as optimization of the pipelines with certain structure. For instance, `allowNull()` may be activated if the pipeline contains no `RNull/RMissing` handling cast node, such as `FindFirstNode` or `CastToVectorNode`. The `mustNotBeNull` configuration may optimize pipelines containing cast nodes raising an error for `RNull/RMissing`, such as the nodes produced by steps `findFirst()`, `findFirst(error)` or `mustBe(singleElement())`. Or the `mapNull(x)` configuration may be applied provided that the pipeline's last step is `findFirst(x)`. - ### Cast Pipeline Optimizations The declarative character of cast pipelines allows for a number of optimizations done during the pipeline construction (some of them are mentioned in the previous section). @@ -257,6 +270,8 @@ Provided that the pipeline contains the `findFirst(x)` step specifying the repla String, double and integer argument values are routed directly after the `FindFirstNode`. On the other hand, logical values bypass the whole pipeline provided that the pipeline ends by the pattern `asLogicalVector()...findFirst().map(toBoolean())`. +For more details see `BypassNode`. + ### Sample Builtins Using Cast Pipelines * [Scan.java](../../com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java) @@ -264,13 +279,13 @@ String, double and integer argument values are routed directly after the `FindFi ### Using `rbdiag` tool -The `mx rbdiag` tool implements the functionality of the static and dynamic stages of the chimney sweeping. This command prints a brief report for each cast pipeline defined in a given builtin. +The `mx rbdiag` tool diagnoses a given builtin or all builtins. This command prints a brief report for each cast pipeline defined in a given builtin including a summary of the diagnosis. -#### Static stage +#### Result type analysis -In the case of the static diagnostics the tool provides information about all possible result types of each argument and how those result types are bound to the corresponding arguments of the builtin's specializations. Importantly, the report can reveal unbound argument types that can potentially cause the missing specialization error. +This analysis provides information about all possible result types of each argument and how those result types are bound to the corresponding arguments of the builtin's specializations. Importantly, the report can reveal unbound argument types that can potentially cause the missing specialization error. Further, it can reveal the so-called __dead__ specializations, i.e. specializations that are never invoked. -It can be illustrated on the `rowsum_matrix` builtin. The `mx` command is then as follows: +This analyis can be illustrated on the `rowsum_matrix` builtin. The `mx` command is then as follows: ```bash mx rbdiag rowsum_matrix @@ -280,13 +295,13 @@ It prints a rather lengthy report, of which the following snippet shows the diag ```bash Pipeline for 'x' (arg[0]): + Warning: Unbound types: + [Integer, Double] Result types union: [Integer, RAbstractIntVector, RAbstractDoubleVector, Double] Bound result types: potential (RAbstractIntVector->RVector) in Object rowsum(*RVector*,RVector,RVector,boolean,RStringVector) potential (RAbstractDoubleVector->RVector) in Object rowsum(*RVector*,RVector,RVector,boolean,RStringVector) - Unbound types: - [Integer, Double] ``` The `Result types union` section lists all result types possibly produced by the pipeline. The `Bound result types` section outlines all bound type; i.e. the argument types for which there is a corresponding specialization in the builtin. In this case, only two argument types - `RAbstractIntVector` and `RAbstractDoubleVector` - are bound to the `rowsum(RVector,RVector,RVector,boolean,RStringVector)` specialization. (The asterisks surrounding the first argument in the specialization indicate the argument to which the type in question is bound). The `potential` flag indicates here that there is an underlying implicit conversion between the type produced by the cast pipeline and the argument type in the specialization. @@ -302,15 +317,13 @@ Nevertheless, there are two arguments left unbound - `Integer` and `Double`. Thi potential (Double->RAbstractVector) in Object rowsum(*RAbstractVector*,RAbstractVector,RAbstractVector,boolean,RAbstractStringVector) full (RAbstractDoubleVector->RAbstractVector) in Object rowsum(*RAbstractVector*,RAbstractVector,RAbstractVector,boolean,RAbstractStringVector) potential (Integer->RAbstractVector) in Object rowsum(*RAbstractVector*,RAbstractVector,RAbstractVector,boolean,RAbstractStringVector) - Unbound types: - [] ``` The produced result types are naturally the same ones, but now all of them are bound. In conclusion, using the abstract types resulted in the binding of the previously unbound types. Note: The `full` flag indicates that the pipeline's type is a subtype of the specialization's argument type. The `partial` flag, which is not seen here, indicates that the pipeline's type is a supertype of the specialization's argument type. The `potential` flag indicates an implicit conversion or a potentially non-empty intersection between the two types, typically if they are both interfaces. -#### Dynamic stage +#### Chimney-sweeping In the dynamic stage, the tool uses the samples inferred from the cast pipelines of a given builtin along with some 'springboard' list of valid arguments to construct a number of argument combinations. These argument lists are then used to invoke both the FastR builtin and its GnuR counterpart. The tool uses the test output file (ExpectedTestOutput.test) to obtain the 'springboard' argument lists for a given builtin. These valid argument lists are reproduced by substituting combinations of generated samples. The varied arguments are then used against both GnuR and FastR. If the two outputs differ, the tool reports the command and the corresponding outputs. diff --git a/documentation/dev/ffi.md b/documentation/dev/ffi.md index 1ebb04860b47e5d8dcf7f51ea3f9edf0b8c81270..0a35d7f1ef0c54804ad51eba9824c44c8c63d6e6 100644 --- a/documentation/dev/ffi.md +++ b/documentation/dev/ffi.md @@ -1,19 +1,24 @@ # The R FFI Implementation # Introduction -FastR interfaces to native C and Fortran code in a number of ways, for example, access to C library APIs not supported by the Java JDK, access to LaPack functions, and the `.Call`, `.Fortran`, `.C` builtins. Each of these are defined by a Java interface,e.g. `CallRFFI` for the `.Call` builtin. To facilitate experimentation and different implementations, the implementation of these interfaces is defined by a factory class, `RFFIFactory`, that is chosen at run time via the `fastr.ffi.factory.class` system property. The factory is responsible for creating an instance of the `RFFI` interface that in turn provides access to implementations of the underlying interfaces such as `CallRFFI`. This structure allows +FastR can interface to native C and Fortran code in a number of ways, for example, access to C library APIs not supported by the Java JDK, access to LaPack functions, and the `.Call`, `.Fortran`, `.C` builtins. Each of these are defined by a Java interface,e.g. `CallRFFI` for the `.Call` builtin. To facilitate experimentation and different implementations, the implementation of these interfaces is defined by a factory class, `RFFIFactory`, that is chosen at run time via the `fastr.ffi.factory.class` system property, or the `FASTR_RFFI` environment variable. +The factory is responsible for creating an instance of the `RFFI` interface that in turn provides access to implementations of the underlying interfaces such as `CallRFFI`. This structure allows for each of the individual interfaces to be implemented by a different mechanism. Currently the default factory class is `JNI_RFFIFactory` which uses the Java JNI system to implement the transition to native code. +# No native code mode +FastR can be configured to avoid running any unmanaged code coming from GNU R or packages. It is described in more detail [here](managed_ffi.md). + # Native Implementation The native implementation of the [R FFI](https://cran.r-project.org/doc/manuals/r-release/R-exts.html) is contained in the `fficall` directory of the `com.oracle/truffle.r.native` project`. It's actually a bit more than that as it also contains code copied from GNU R, for example that supports graphics or is sufficiently simple that it is neither necessary nor desirable to implement in Java. As this has evolved a better name for `fficall` would probably be `main` for compatibility with GNU R. - There are four sub-directories in `fficall/src`: + There are five sub-directories in `fficall/src`: * `include` * `common` * `jni` + * `truffle_nfi` * `truffle_llvm` ## The `fficall/include` directory @@ -44,7 +49,11 @@ copied/included from GNU R. N.B. Some modified files have a `_fastr` suffix to a the Makefile rule for compiling directly from the GNU R file. ## The `jni` directory -`jni` contains the implementation that is based on and has explicit dependencies on Java JNI. It is described in more detail [here](jni_ffi.md) +`jni` contains the implementation that is based on and has explicit dependencies on Java JNI. It is described in more detail [here](jni_ffi.md). This is the default implementation. + +## The `truffle_nfi` directory. +`truffle_nfi` contains the implementation that is based on the Truffle Native Function Interface. It is enabled by setting `FASTR_RFFIU=nfi` and doing a clean build. +The implementation is currently incomplete. ## The `truffle_llvm` directory @@ -52,7 +61,7 @@ the Makefile rule for compiling directly from the GNU R file. # RFFI Initialization Not all of the individual interfaces need to be instantiated on startup. The `getXXXRFFI()` method of `RFFI` is responsible for instantiating the `XXX` interface (e.e.g `Call`). -However, the factory can choose to instantiate the interfqces eagerly if desired. The choice of factory class is made by `RFFIFactory.initialize()` which is called when the +However, the factory can choose to instantiate the interfaces eagerly if desired. The choice of factory class is made by `RFFIFactory.initialize()` which is called when the initial `RContext` is being created by `PolyglotEngine`. Note that at this stage, very little code can be executed as the initial context has not yet been fully created and registered with `PolyglotEngine`. In general, state maintained by the `RFFI` implementation classes is `RContext` specific and to facilitate this `RFFIFactory` defines a `newContextState` method that is called by `RContext`. Again, at the point this is called the context is not active and so any execution that requires an active context must be delayed until the `initialize` method is called on the `ContextState` instance. Typically special initialization may be required on the initialization of the initial context, such as loading native libraries, and also on the initialization of a `SHARED_PARENT_RW` context kind. diff --git a/documentation/dev/managed_ffi.md b/documentation/dev/managed_ffi.md new file mode 100644 index 0000000000000000000000000000000000000000..4e07641430cc13487e861d24c288b7e112db7a2a --- /dev/null +++ b/documentation/dev/managed_ffi.md @@ -0,0 +1,25 @@ + +# Quick start +FastR supports a 'managed' mode, in which it does not execute any native code directly, especially code coming from GNU R and packages, +and tries to avoid other potentially security sensitive code, e.g. instrumentation agents. To enable this mode, clean build and run +FastR with environment variable `FASTR_MANAGED` set to *true*. + +# Details +FastR has an 'implementation' of RFFI that does not use any native code directly (e.g. through JNI) and implements only small subset of the API. +Any usage of the unimplemented parts will cause error at runtime. To enable this RFFI implementation clean build FastR with environment variable +`FASTR_RFFI` set to *managed* and when running FastR set java property named *fastr.rffi.factory.class* to +`com.oracle.truffle.r.runtime.ffi.managed.Managed_RFFIFactory`. + +There are additional options that can restrict other usages of native code in FastR: + +* When FastR option `LoadPackagesNativeCode=false`, then FastR does not load builtin packages (graphics and base) native code. +Note that loading of their native code is going to fail with *managed* RFFI implementation. +* When FastR option `LoadProfiles=false`, then FastR does not load user profile, machine profile etc. Those scripts typically use +some R code that ends up trying to call native code, which is again going to fail with *managed* RFFI implementation. +* Set `FastRConfig#InternalGridAwtSupport` to `false` before building FastR. This should remove usages of AWT from FastR's +bytecode and thus reduce the amount of native code that can be invoked by running arbitrary R code in FastR. + +Following option can be useful for improving security when running FastR: + +* Set java property *fastr.objectsize.factory.class* to `com.oracle.truffle.r.runtime.data.SimpleObjectSizeFactory` to avoid +usage of otherwise more precise `AgentObjectSizeFactory`, which uses instrumentation agent. diff --git a/documentation/dev/testing.md b/documentation/dev/testing.md index a3a1bf75f1a92dbaf95b5cf9b0cf5b7c835bfdb5..a5a2718be1a78c80dc8ebd3ccca71ea017dbd3a9 100644 --- a/documentation/dev/testing.md +++ b/documentation/dev/testing.md @@ -10,8 +10,7 @@ The unit testing works by executing the R test and the comparing the output with The unit tests reside mainly in the `com.oracle.truffle.r.test` project, with a smaller number in the and `com.oracle.truffle.r.nodes.test` project. To execute the unit tests use the `mx junit` command. The standard set of unit tests is available via the `mx junitdefault` command and the following additional variants are available: 1. `mx junitsimple`: everything except the package tests and the `com.oracle.truffle.r.nodes.test` -2. `mx junitnopkgs`: everything except the package tests -3. `mx junit --tests list`: `list` is a comma-separated list of test patterns, where a pattern is a package or class. For example to just run the "builtin" tests run `mx junit --tests com.oracle.truffle.r.test.builtins`. +2. `mx junit --tests list`: `list` is a comma-separated list of test patterns, where a pattern is a package or class. For example to just run the "builtin" tests run `mx junit --tests com.oracle.truffle.r.test.builtins`. As with most FastR `mx` commands, additional parameters can be passed to the underlying FastR process using the `--J` option. For example to debug a unit test under an IDE, it is important to disable the internal timeout mechanism that detects looping tests, vis: @@ -55,16 +54,16 @@ Package developers can provide tests in several ways. To enable the full set of ### Package Installation and Testing -Package installation and testing is partly handled by a R script `install_cran_packages.R` in the `com.oracle.truffle.r.test.cran` project and partly by an `mx` script. There are two relevant `mx` commands, `installpkgs` and `pkgtest`. The former is simply a wrapper to `install_cran_packages.R`, whereas `pkgtest` contains additional code to gather and compare test outputs. +Package installation and testing is partly handled by a R script `r/install.packages.R` in the `com.oracle.truffle.r.test.packages` project and partly by an `mx` script. There are two relevant `mx` commands, `installpkgs` and `pkgtest`. The former is simply a wrapper to `install.packages.R`, whereas `pkgtest` contains additional code to gather and compare test outputs. -#### The install_cran_packages.R script +#### The install.packages.R script While normally run with FastR using the `mx installpkgs` wrapper, this script can be used standalone using `Rscript`, thereby allowing to to be used by GNU R also. The command has a rather daunting set of options but, for normal use, most of these do not need to be set. ##### Usage - mx installpkgs [--contriburl url] [--cran-mirror url] + mx installpkgs [--repos list] [--verbose | -v] [-V] [--dryrun] [--no-install | -n] @@ -94,26 +93,24 @@ Key concepts are discussed below. ##### Package Blacklist -There are many packages that cannot be installed due to either missing functionality or fundamental limitations in FastR and this set is seeded from a a DCF file, `initial.package.blacklist`, in the `com.oracle.truffle.r.test.cran` project. `install_cran_packages` operates in two modes, either creating a complete blacklist from an initial blacklist or reading a previously created blacklist file. In the latter case, if the blacklist file does not exist, it will be created. The complete blacklist file can specified in three ways: +There are many packages that cannot be installed due to either missing functionality or fundamental limitations in FastR and this set is seeded from a a DCF file, `initial.package.blacklist`, in the `com.oracle.truffle.r.test.packages` project. `install.packages` operates in two modes, either creating a complete blacklist from an initial blacklist or reading a previously created blacklist file. In the latter case, if the blacklist file does not exist, it will be created. The complete blacklist file can be specified in three ways: -1. using the command line argument `--blacklist-file` -2. from the environment variable `PACKAGE_BLACKLIST` -3. the file `package.blacklist` - -The alternatives are tried in order. So, usually, this is all automatic. +1. using the command line argument `--blacklist-file`; if omitted defaults to the file `package.blacklist` +2. TODO +3. TODO ##### CRAN Mirror -Packages are downloaded and installed from a CRAN mirror. When the standard `utils::install_packages` function is run interactively, the user is prompted for a mirror. To avoid such interaction, `install_cran_packages` has a number of ways of specifying a mirror, including the use of a "local mirror" in the file system. The default CRAN mirror is `http://cran.cnr.berkeley.edu/` but this can be changed either with the command line argument `--cran-mirror` or the environment variable `CRAN_MIRROR`. When running locally a file system copy of a CRAN mirror containing just the `src/contrib` directory can be used by either setting the command line argument `--contrib-url` or the `LOCAL_CRAN_REPO` environment variable to a file: URL, e.g. `file:///users/mjj/cran/LOCAL_REPO/src/contrib`. +Packages are downloaded and installed from the repos given by the `repos` argument, a comma-separated list of `name[=value]` pairs, that defaults to `CRAN`. CRAN packages are downloaded from a CRAN mirror. When the standard `utils::install_packages` function is run interactively, the user is prompted for a mirror. To avoid such interaction, `install.packages` has two ways for specifying a mirror. The default CRAN mirror is `http://cran.cnr.berkeley.edu/` but this can be changed either with `CRAN=url` or the environment variable `CRAN_MIRROR`. The `FASTR` repo is internal to the source base and contains FastR-specific test packages. The BioConductor repo can be added by setting `--repos BIOC`. User defined repos can be specified by `USERNAME=url`. N.B. For file system paths this must be a `file:` URL. ##### Installation Directory -The directory in which to install the package can be specified either by setting the `R_LIBS_USER` environment variable or with the `--lib` command line argument. The former is recommended and indeed required for running tests after installation. +The directory in which to install the package can be specified either by setting the `R_LIBS_USER` environment variable or with the `--lib` command line argument. The former is recommended and indeed required for running tests after installation (the testing system does not honor the `--lib` argument). ##### Specifying packages to Install -If the `--pkg-filelist` argument is provided then the associated file should contain a list of packages to install, one per line. Otherwise if a package pattern argument is given, then all packages matching the (R) regular expression are candidates for installation, otherwise all available packages are candidates, computed by invoking the `available.packages()` function. The candidate set can be adjusted with additional options. The `--use-installed.pkgs` option will cause `install_cran_packages` to analyze the package installation directory for existing successfully installed packages and remove those from the candidate set. Some convenience options implicitly set `--pkg-filelist`, namely: +If the `--pkg-filelist` argument is provided then the associated file should contain a list of packages to install, one per line. Otherwise if a package pattern argument is given, then all packages matching the (R) regular expression are candidates for installation, otherwise all available packages are candidates, computed by invoking the `available.packages()` function. The candidate set can be adjusted with additional options. The `--use-installed-pkgs` option will cause `install.packages` to analyze the package installation directory for existing successfully installed packages and remove those from the candidate set for installation. This option is implied by `--no-install`. Some convenience options implicitly set `--pkg-filelist`, namely: - --ok-only: sets it to the file `com.oracle.truffle.r.test.cran.ok.packages`. This file is a list of packages that are known to install. + --ok-only: sets it to the file `com.oracle.truffle.r.test.packages/ok.packages`. This file is a list of packages that are known to install. -N.B. The is file is updated only occasionally. Regressions, bug fixes, can render it inaccurate. +N.B. This file is updated only occasionally. Regressions, bug fixes, can render it inaccurate. Two options are designed to be used for a daily package testing run. These are based on the day of the year and install/test a rolling set of packages: @@ -125,18 +122,18 @@ Finally, the `--invert-pkgset` option starts with the set from `available.packag N.B. By default the candidate set is always reduced by omitting any package in the package blacklist set, but this can be turned off by setting `--ignore-blacklist`. N.B. also that `--pkg-filelist` and `--pkg-pattern` are mutually exclusive. ##### Installing Dependent Packages: -`install_cran_packages` installs the list of requested packages one by one. By default `utils::install.packages` always installs dependent packages, even if the dependent package has already been installed. This can be particularly wasteful if the package fails to install. Setting `--install-dependents-first` causes `install_cran_packages` to analyse the dependents and install them one by one first, aborting the installation of the depending package if any fail. +`install.packages` installs the list of requested packages one by one. By default `utils::install.packages` always installs dependent packages, even if the dependent package has already been installed. This can be particularly wasteful if the package fails to install. Setting `--install-dependents-first` causes `install.packages` to analyse the dependents and install them one by one first, aborting the installation of the depending package if any fail. ##### Run Mode -GNU R uses R/Rscript sub-processes in the internals of package installation and testing, but multiple package installations (e.g. using `--pkg-filelist`) would normally be initiated from a single top-level R process. This assumes that the package installation process itself is robust. This mode is defined as the `internal` mode variant of the `--run-mode` option. Since FastR is still under development, in `internal` mode a failure of FastR during a single package installation would abort the entire `install_cran_packages` execution. Therefore by default `install_cran_packages` runs each installation in a separate FastR sub-process, referred to as `system` mode (because the R `system` function is used to launch the sub-process). +GNU R uses R/Rscript sub-processes in the internals of package installation and testing, but multiple package installations (e.g. using `--pkg-filelist`) would normally be initiated from a single top-level R process. This assumes that the package installation process itself is robust. This mode is defined as the `internal` mode variant of the `--run-mode` option. Since FastR is still under development, in `internal` mode a failure of FastR during a single package installation would abort the entire `install.packages` execution. Therefore by default `install.packages` runs each installation in a separate FastR sub-process, referred to as `system` mode (because the R `system` function is used to launch the sub-process). -When running `install_cran_packages` under GNU R, it makes sense to set `--run-mode internal`. +When running `install.packages` under GNU R, it makes sense to set `--run-mode internal`. ##### Use with GNU R Basic usage is: - $ Rscript $FASTR_HOME/fastr/com.oracle.truffle.r.test.cran/r/install.cran.packages.R --run-mode internal [options] + $ Rscript $FASTR_HOME/fastr/com.oracle.truffle.r.test.packages/r/install.packages.R --run-mode internal [options] where `FASTR_HOME` is the location of the FastR source. @@ -148,7 +145,7 @@ Testing packages requires that they are first installed, so all of the above is --verbose | -v: output tracing on basic steps -V: more verbose tracing --dry-run: output what would be installed but don't actually install - --no-install | -n: suppress installation phase (useful for --create blacklist and --use-installed-packages/--run-tests) + --no-install | -n: suppress installation phase (useful for --create blacklist and --run-tests) --random count: install count packages randomly chosen from the candidate set --testdir dir: store test output in dir (defaults to "test"). --print-ok-installs: print the successfully installed packages @@ -157,11 +154,15 @@ Testing packages requires that they are first installed, so all of the above is #### Examples - $ export R_LIBS_USER=`pwd`/lib.install.cran + $ export R_LIBS_USER=`pwd`/lib.install.packages $ mx installpkgs --pkg-pattern '^A3$' -Install the A3 package (and its dependents) in `$R_LIBS_USER`, creating the `package.blacklist` file first if it does not exist. The dependents (xtable, pbapply) will be installed implicitly by the underlying R install.packages function +Install the `A3` package (and its dependents) in `$R_LIBS_USER`, creating the `package.blacklist` file first if it does not exist. The dependents (`xtable`, `pbapply`) will be installed implicitly by the underlying R install.packages function + + $ mx installpkgs --repos CRAN=file://path-to-local-cran-mirror --pkg-pattern '^A3$' + +Similar to above but uses a local CRAN mirror stored in `path-to-local-cran-mirror`. $ mx installpkgs --install-dependents-first--pkg-pattern '^A3$' @@ -177,7 +178,7 @@ Install exactly those packages (and their dependents) specified, one per line, i $ mx installpkgs --ok-only --invert-pkgset --random-count 100 -Install 100 randomly chosen packages that are not in the file `com.oracle.truffle.r.test.cran/ok.packages`. +Install 100 randomly chosen packages that are not in the file `com.oracle.truffle.r.test.packages/ok.packages`. $ mx installpkgs --ignore-blacklist '^Rcpp$' @@ -185,7 +186,9 @@ Override the blacklist and attempt to install the `Rcpp` package. N.B. The regul #### The mx pkgtest command -The `mx pkgtest` command is a wrapper on `mx installpkgs` that forces the `--run-tests` option and also executes the same tests under GnuR and compares the results. In order to run the tests under GnuR, the `gnur` suite must be installed as a sibling to `fastr`. +The `mx pkgtest` command is a wrapper on `mx installpkgs` that forces the `--run-tests` option and also executes the same tests under GnuR and compares the results. The packages are installed into `lib.install.packages.fastr` and `lib.install.packages.gnur`, respectively and the test results are stored in `test.fastr` and `test.gnur`, respectively. The differences between the results, computed using `diff -r`, are stored per package in the `test.diffs` directory. All these directories are cleaned and re-created at the start of the run. + +By default the local build of FastR and the internal GNU R that is built as part of the FastR build are used to run the tests. However, when `FASTR_GRAALVM` is set to the location of a `GraalVM` binary installation, that is used for FastR and the `gnur` suite must be installed and built as a sibling to `fastr`. #### Running/Debugging Tests Locally @@ -193,6 +196,6 @@ To debug why a test fails requires first that the package is installed locally p $ FASTR_LOG_SYSTEM=1 mx installpkgs '^digest$' -First, note that, by default, the `installpkgs` command itself introduces an extra level on sub-process in order to avoid a failure from aborting the entire install command when installing/testing multiple packages. You can see this by setting the environment variable `FASTR_LOG_SYSTEM` to any value. The first sub-process logged will be running the command `com.oracle.truffle.r.test.cran/r/install.package.R` and the second will be the one running `R CMD INSTALL --install-tests` of the digest package. For ease of debugging you can set the `--run-mode` option to `internal`, which executes the first phase of the install in the process running `installpkgs`. Similar considerations apply to the testing phase. By default a sub-process is used to run the `com.oracle.truffle.r.test.cran/r/test.package.R script`, which then runs the actual test using a sub-process to invoke `R CMD BATCH`. Again the first sub-process can be avoided using `--run-mode internal`. N.B. If you run the tests for `digest` you will see that there are four separate sub-processes used to run different tests. The latter three are the specific tests for digest that were made available by installing with `--install-tests`. Not all packages have such additional tests. Note that there is no way to avoid the tests being run in sub-processes so setting the `-d` option to the `installpkgs` command will have no effect on those. Instead set the environment variable `MX_R_GLOBAL_ARGS=-d` which will cause the sub-processes to run under the debugger. Note that you will not (initially) see the `Listening for transport dt_socket at address: 8000` message on the console, but activating the debug launch from the IDE will connect to the sub-process. +First, note that, by default, the `installpkgs` command itself introduces an extra level on sub-process in order to avoid a failure from aborting the entire install command when installing/testing multiple packages. You can see this by setting the environment variable `FASTR_LOG_SYSTEM` to any value. The first sub-process logged will be running the command `com.oracle.truffle.r.test.packages/r/install.package.R` and the second will be the one running `R CMD INSTALL --install-tests` of the digest package. For ease of debugging you can set the `--run-mode` option to `internal`, which executes the first phase of the install in the process running `installpkgs`. Similar considerations apply to the testing phase. By default a sub-process is used to run the `com.oracle.truffle.r.test.packages/r/test.package.R script`, which then runs the actual test using a sub-process to invoke `R CMD BATCH`. Again the first sub-process can be avoided using `--run-mode internal`. N.B. If you run the tests for `digest` you will see that there are four separate sub-processes used to run different tests. The latter three are the specific tests for digest that were made available by installing with `--install-tests`. Not all packages have such additional tests. Note that there is no way to avoid the tests being run in sub-processes so setting the `-d` option to the `installpkgs` command will have no effect on those. Instead set the environment variable `MX_R_GLOBAL_ARGS=-d` which will cause the sub-processes to run under the debugger. Note that you will not (initially) see the `Listening for transport dt_socket at address: 8000` message on the console, but activating the debug launch from the IDE will connect to the sub-process. diff --git a/documentation/dev/truffle_llvm_ffi.md b/documentation/dev/truffle_llvm_ffi.md index 8eb7fd13ca344734107b2a70c0e9a4a9ce37aae1..511d667d43f38135dc850ca0aa6ed0ae5e01da8a 100644 --- a/documentation/dev/truffle_llvm_ffi.md +++ b/documentation/dev/truffle_llvm_ffi.md @@ -15,7 +15,7 @@ The `sulong` repository must be cloned to a sibling directory of `fastr` and bui mx build mx su-pulldragonegg -The `mx build` step will clone the `graal-core` repository, if necessary, and build that also. The `mx su-pulldragonegg` step is required to be able to compile Fortran code to LLVM, which is required by FastR. +The `mx build` step will clone the `compiler` repository, if necessary, and build that also. The `mx su-pulldragonegg` step is required to be able to compile Fortran code to LLVM, which is required by FastR. ## Additional Pre-Requisites diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides index 9ace1ab1d3a27e419cea334c91beb3be453f17cd..3479fff1b86814164245efe99a1b38315fe81fe1 100644 --- a/mx.fastr/copyrights/overrides +++ b/mx.fastr/copyrights/overrides @@ -1,31 +1,5 @@ -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/BaseGraphicsSystem.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/AbstractGraphicsSystem.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/CoordinatesDrawableObject.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/DrawableObject.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/PolylineDrawableObject.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/StringDrawableObject.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/DrawingParameters.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/Axis.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/AxisDirection.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/Coordinates.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/CoordinatesFactory.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/CoordinateSystem.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/DoubleCoordinates.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/IntCoordinates.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsDevice.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngine.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngineImpl.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEvent.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystem.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystemParameters.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRComponent.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java,gnu_r_graphics.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/fastrgd/FastRGraphicsDevice.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/NullGraphicsDevice.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/pdf/PdfGraphicsDevice.java,gnu_r_graphics.copyright -com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java,gnu_r_graphics.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java,gnu_r.copyright com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java,gnu_r.copyright com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Arithmetic.java,gnu_r_gentleman_ihaka.copyright @@ -140,9 +114,11 @@ com.oracle.truffle.r.native/fficall/src/include/rlocale.h,gnu_r_gentleman_ihaka. com.oracle.truffle.r.native/fficall/src/jni/Memory.c,gnu_r.copyright com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c,gnu_r_gentleman_ihaka2.copyright com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c,gnu_r.copyright +com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c,gnu_r.copyright +com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c,gnu_r.copyright +com.oracle.truffle.r.native/fficall/src/truffle_nfi/pcre_rffi.c,gnu_r_gentleman_ihaka2.copyright com.oracle.truffle.r.native/fficall/src/truffle_llvm/Rdynload_fastr.c,gnu_r.copyright com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c,gnu_r.copyright -com.oracle.truffle.r.native/include/src/libintl.h,no.copyright com.oracle.truffle.r.native/library/base/src/registration.c,no.copyright com.oracle.truffle.r.native/library/grDevices/src/gzio.c,gnu_r_gentleman_ihaka.copyright com.oracle.truffle.r.native/library/methods/src/methods_dummy.c,no.copyright @@ -207,6 +183,7 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/L com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java,gnu_r_gentleman_ihaka2.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java,gnu_r_gentleman_ihaka.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java,gnu_r_gentleman_ihaka2.copyright +com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrettyIntevals.java,gnu_r_gentleman_ihaka2.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java,gnu_r_gentleman_ihaka.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java,gnu_r_gentleman_ihaka.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java,purdue.copyright @@ -683,7 +660,6 @@ com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sub com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_subset2.java,purdue.copyright com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substitute.java,purdue.copyright com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substr.java,purdue.copyright -com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substrassign_.java,purdue.copyright com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substrassign.java,purdue.copyright com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substring.java,purdue.copyright com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sum.java,purdue.copyright @@ -764,3 +740,38 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/p com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java,gnu_r_gentleman_ihaka2.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java,gnu_r_gentleman_ihaka2.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java,gnu_r_gentleman_ihaka2.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPretty.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Arrows.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUpViewPort.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java,gnu_r_murrel_core.copyright +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/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 +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java,gnu_r_murrel_core.copyright +com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java,gnu_r_gentleman_ihaka2.copyright diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py index 5e9c6ebfd3344ee1405840869061861a8af54bc6..4eac3bba913e9a318b1e888f7a8fe891ba02e65e 100644 --- a/mx.fastr/mx_fastr.py +++ b/mx.fastr/mx_fastr.py @@ -29,7 +29,7 @@ import mx_fastr_pkgs import mx_fastr_compile import mx_fastr_dists import mx_fastr_junit -from mx_fastr_dists import FastRNativeProject, FastRTestNativeProject, FastRReleaseProject, FastRNativeRecommendedProject #pylint: disable=unused-import +from mx_fastr_dists import FastRTestNativeProject, FastRReleaseProject, FastRNativeRecommendedProject #pylint: disable=unused-import import mx_copylib import mx_fastr_mkgramrd import mx_fastr_edinclude @@ -39,7 +39,7 @@ import os ''' This is the launchpad for all the functions available for building/running/testing/analyzing FastR. FastR can run with or without the Graal compiler enabled. As a convenience if the -graal-core suite is detected then the use of the Graal compiler is enabled without any +compiler suite is detected then the use of the Graal compiler is enabled without any additional command line options being required to the mx command, i.e. it is as if --jdk jvmci was passed as an mx global option. ''' @@ -48,7 +48,7 @@ _fastr_suite = mx.suite('fastr') ''' If this is None, then we run under the standard VM in interpreted mode only. ''' -_mx_graal = mx.suite("graal-core", fatalIfMissing=False) +_mx_graal = mx.suite("compiler", fatalIfMissing=False) _mx_sulong = mx.suite("sulong", fatalIfMissing=False) _r_command_package = 'com.oracle.truffle.r.engine' @@ -295,10 +295,6 @@ def rgate(args): ''' mx_gate.gate(args) -def gate(args): - '''Run 'mx.gate' with some standard tasks excluded as they currently fail''' - mx_gate.gate(args + ['-x', '-t', 'FindBugs,Checkheaders,Distribution Overlap Check,BuildJavaWithEcj']) - def _test_srcdir(): tp = 'com.oracle.truffle.r.test' return join(mx.project(tp).dir, 'src', tp.replace('.', sep)) @@ -391,9 +387,6 @@ def junit_simple(args): def junit_noapps(args): return mx.command_function('junit')(['--tests', _gate_noapps_unit_tests()] + args) -def junit_nopkgs(args): - return mx.command_function('junit')(['--tests', ','.join([_simple_unit_tests(), _nodes_unit_tests()])] + args) - def junit_default(args): return mx.command_function('junit')(['--tests', _all_unit_tests()] + args) @@ -407,14 +400,11 @@ def _test_subpackage(name): return '.'.join((_test_package(), name)) def _simple_generated_unit_tests(): - return ','.join(map(_test_subpackage, ['library.base', 'library.grid', 'library.methods', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'S4', 'rng', 'runtime.data'])) + return ','.join(map(_test_subpackage, ['engine.shell', 'library.base', 'library.fastrGrid', 'library.methods', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'rng', 'runtime.data', 'S4'])) def _simple_unit_tests(): return ','.join([_simple_generated_unit_tests(), _test_subpackage('tck')]) -def _package_unit_tests(): - return ','.join(map(_test_subpackage, ['rffi', 'rpackages'])) - def _nodes_unit_tests(): return 'com.oracle.truffle.r.nodes.test' @@ -422,7 +412,7 @@ def _apps_unit_tests(): return _test_subpackage('apps') def _gate_noapps_unit_tests(): - return ','.join([_simple_unit_tests(), _nodes_unit_tests(), _package_unit_tests()]) + return ','.join([_simple_unit_tests(), _nodes_unit_tests()]) def _gate_unit_tests(): return ','.join([_gate_noapps_unit_tests(), _apps_unit_tests()]) @@ -431,7 +421,7 @@ def _all_unit_tests(): return _gate_unit_tests() def _all_generated_unit_tests(): - return ','.join([_simple_generated_unit_tests(), _package_unit_tests()]) + return ','.join([_simple_generated_unit_tests()]) def testgen(args): '''generate the expected output for unit tests, and All/Failing test classes''' @@ -585,13 +575,11 @@ _commands = { 'Rscript' : [rscript, '[options]'], 'rtestgen' : [testgen, ''], 'rgate' : [rgate, ''], - 'gate' : [gate, ''], 'junit' : [junit, ['options']], 'junitsimple' : [junit_simple, ['options']], 'junitdefault' : [junit_default, ['options']], 'junitgate' : [junit_gate, ['options']], 'junitnoapps' : [junit_noapps, ['options']], - 'junitnopkgs' : [junit_nopkgs, ['options']], 'unittest' : [unittest, ['options']], 'rbcheck' : [rbcheck, '--filter [gnur-only,fastr-only,both,both-diff]'], 'rbdiag' : [rbdiag, '(builtin)* [-v] [-n] [-m] [--sweep | --sweep=lite | --sweep=total] [--mnonly] [--noSelfTest] [--matchLevel=same | --matchLevel=error] [--maxSweeps=N] [--outMaxLev=N]'], @@ -599,6 +587,7 @@ _commands = { 'rembed' : [rembed, '[options]'], 'r-cp' : [r_classpath, '[options]'], 'pkgtest' : [mx_fastr_pkgs.pkgtest, ['options']], + 'pkgtest-cmp' : [mx_fastr_pkgs.pkgtest_cmp, ['gnur_path fastr_path']], 'installpkgs' : [mx_fastr_pkgs.installpkgs, '[options]'], 'mkgramrd': [mx_fastr_mkgramrd.mkgramrd, '[options]'], 'rcopylib' : [mx_copylib.copylib, '[]'], diff --git a/mx.fastr/mx_fastr_dists.py b/mx.fastr/mx_fastr_dists.py index 3892b38573639e87efb45c1d060868e6b15934f2..2f81965b06e1e888b039f925cb09a2e43338ea3d 100644 --- a/mx.fastr/mx_fastr_dists.py +++ b/mx.fastr/mx_fastr_dists.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. +# 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 @@ -43,74 +43,6 @@ class FastRProjectAdapter(mx.ArchivableProject): results.append(join(root, f)) -class FastRNativeProject(FastRProjectAdapter): - ''' - Custom class for building the com.oracle.truffle.r.native project. - The customization is to support the creation of an exact FASTR_NATIVE_DEV distribution. - ''' - def __init__(self, suite, name, deps, workingSets, theLicense, **args): - FastRProjectAdapter.__init__(self, suite, name, deps, workingSets, theLicense) - - def getBuildTask(self, args): - return mx.NativeBuildTask(args, self) - - def _get_gnur_files(self, gnur_dir, files, results): - for f in files: - results.append(join(self.dir, gnur_dir, f)) - - def getResults(self): - ''' - Capture all the files from the com.oracle.truffle.r.native project that are needed - in an alternative implementation of the R FFI. This includes some files from GNU R. - This code has to be kept in sync with the FFI implementation. - ''' - # plain files - results = [join(self.dir, "platform.mk")] - gnur = join('gnur', mx_fastr.r_version()) - gnur_appl = join(gnur, 'src', 'appl') - self._get_gnur_files(gnur_appl, ['pretty.c', 'interv.c'], results) - gnur_main = join(gnur, 'src', 'main') - self._get_gnur_files(gnur_main, ['colors.c', 'devices.c', 'engine.c', 'format.c', 'graphics.c', - 'plot.c', 'plot3d.c', 'plotmath.c', 'rlocale.c', 'sort.c'], results) - # these files are not compiled, just "included" - self._get_gnur_files(gnur_main, ['xspline.c', 'rlocale_data.h'], results) - # directories - for d in ["fficall/src/common", "fficall/src/include", "fficall/src/variable_defs"]: - self._get_files(d, results) - - def is_dot_h(f): - ext = os.path.splitext(f)[1] - return ext == '.h' - - # just the .h files from 'include' - self._get_files('include', results, is_dot_h) - - # tools for alternate impl of gramRd.c - gnur_tools = join(gnur, 'library', 'tools') - self._get_files(gnur_tools, results) - gnur_tools_src = join(gnur, 'src', 'library', 'tools', 'src') - for f in ['gramRd.c', 'init.c', 'tools.h']: - results.append(join(self.dir, gnur_tools_src, f)) - for f in ['lib.mk', 'Makefile', 'tools/src/tools_dummy.c', 'tools/src/gramRd_fastr.h', 'tools/Makefile']: - results.append(join(self.dir, 'library', f)) - - # selected headers from GNU R source - with open(join(self.dir, 'fficall/src/include/gnurheaders.mk')) as f: - lines = f.readlines() - for line in lines: - if '$(GNUR_HOME)' in line: - parts = line.split(' ') - results.append(join(self.dir, parts[2].rstrip().replace('$(GNUR_HOME)', gnur))) - - def is_ddot_o(f): - ext = os.path.splitext(f)[1] - return f[0] == 'd' and ext == '.o' - - # binary files from GNU R - self._get_files(gnur_appl, results, is_ddot_o) - - return results - class FastRTestNativeProject(FastRProjectAdapter): ''' Custom class for building the com.oracle.truffle.r.native project. @@ -131,18 +63,7 @@ class FastRTestNativeProject(FastRProjectAdapter): results = [] self._get_files(join('packages', 'recommended'), results) - - fastr_packages = [] - fastr_packages_dir = join(self.dir, 'packages') - for root, dirs, _ in os.walk(fastr_packages_dir): - for d in dirs: - if d == 'recommended': - continue - if os.path.isdir(join(root, d)): - fastr_packages.append(d) - break - for p in fastr_packages: - results.append(join(fastr_packages_dir, p, 'lib', p + '.tar')) + self._get_files(join('packages', 'repo'), results) results.append(join(self.dir, 'urand', 'lib', 'liburand.so')) return results diff --git a/mx.fastr/mx_fastr_edinclude.py b/mx.fastr/mx_fastr_edinclude.py index dc211cdd32c068b3fdf4ea24e1b4e0c0c2031209..dce5109799b948d7dec404ff2724f92ef4f31235 100644 --- a/mx.fastr/mx_fastr_edinclude.py +++ b/mx.fastr/mx_fastr_edinclude.py @@ -47,6 +47,7 @@ def edinclude(args): ed_r_internals(args[0]) ed_r_interface(args[0]) ed_graphicsengine(args[0]) + ed_rconfig(args[0]) use_internals_section = '''#ifdef FASTR // packages defining USE_INTERNALS expect certain defs (e.g. isNull) to be there @@ -61,6 +62,19 @@ sexp = '''#ifdef FASTR typedef void *SEXP; #define DATAPTR(x)\t\tR_DATAPTR(x) void *(R_DATAPTR)(SEXP x); + +#define IS_BYTES IS_BYTES +#define IS_LATIN1 IS_LATIN1 +#define IS_ASCII IS_ASCII +#define IS_UTF8 IS_UTF8 +#define ENC_KNOWN ENC_KNOWN + +Rboolean IS_BYTES(SEXP x); +Rboolean IS_LATIN1(SEXP x); +Rboolean IS_ASCII(SEXP x); +Rboolean IS_UTF8(SEXP x); +Rboolean ENC_KNOWN(SEXP x); + #else ''' use_internals_begin = '''#if defined (USE_RINTERNALS_DEFS) && (defined (USE_RINTERNALS) || defined (FASTR)) @@ -206,3 +220,19 @@ def ed_graphicsengine(gnu_dir): f.write(line.replace('24', '256')) else: f.write(line) + +def ed_rconfig(gnu_dir): + ''' + GNU R is built with ENABLE_NLS (internationalized strings) but FastR + does not do that in native code, so we disable it. + ''' + rconfig_h = join(gnu_dir, 'Rconfig.h') + with open(rconfig_h) as f: + lines = f.readlines() + + with open(join('Rconfig.h'), 'w') as f: + for line in lines: + if 'ENABLE_NLS' in line: + continue + else: + f.write(line) diff --git a/mx.fastr/mx_fastr_junit.py b/mx.fastr/mx_fastr_junit.py index 98aa47d398fb19e4b35b677ef1842a2bef0f42d2..9f9555149705ef90c8b13dcf8a98d88f8855b0ed 100644 --- a/mx.fastr/mx_fastr_junit.py +++ b/mx.fastr/mx_fastr_junit.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. +# 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 @@ -76,7 +76,10 @@ def junit(args, harness, parser=None, jdk_default=None): if not found: mx.warn('no tests matched by substring "' + t + '"') - vmArgs += mx.get_runtime_jvm_args([pcp.name for pcp in mx.projects(opt_limit_to_suite=True) if pcp.isJavaProject() and pcp.javaCompliance <= jdk.javaCompliance], jdk=jdk) + dists = ['FASTR', 'FASTR_UNIT_TESTS'] + if mx.suite('r-apptests', fatalIfMissing=False): + dists.append('com.oracle.truffle.r.test.apps') + vmArgs += mx.get_runtime_jvm_args(dists, jdk=jdk) if len(classes) != 0: if len(classes) == 1: diff --git a/mx.fastr/mx_fastr_mkgramrd.py b/mx.fastr/mx_fastr_mkgramrd.py index a951e04a1491d38e3e2bc675e8ac292348565e0b..d01b63fc38dfc1aaa7c1552bc490e6cf98d2f13b 100644 --- a/mx.fastr/mx_fastr_mkgramrd.py +++ b/mx.fastr/mx_fastr_mkgramrd.py @@ -44,7 +44,7 @@ extern SEXP FASTR_R_EmptyEnv(); extern SEXP R_NewHashedEnv(SEXP a, SEXP b); char *dgettext(const char *p, const char *msgid) { -return msgid; +return (char *)msgid; } int imax2(int x, int y) diff --git a/mx.fastr/mx_fastr_pkgs.py b/mx.fastr/mx_fastr_pkgs.py index 874dbf5e651d0f7df036a77780e047dc0dff5cec..0e7fe3319fc8c82c75c152cd0defda535e9c73e4 100644 --- a/mx.fastr/mx_fastr_pkgs.py +++ b/mx.fastr/mx_fastr_pkgs.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. +# 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 @@ -25,12 +25,12 @@ The pkgtest command operates in two modes: 1. In development mode it uses the FastR 'Rscript' command and the internal GNU R for test comparison 2. In production mode it uses the GraalVM 'Rscript' command and a GNU R loaded as a sibling suite. This is indicated -by the environment variable 'GRAALVM_FASTR' being set. +by the environment variable 'FASTR_GRAALVM' being set. (GRAALVM_FASTR is also accepted for backwards cmpatibility) Evidently in case 2, there is the potential for a version mismatch between FastR and GNU R, and this is checked. In either case all the output is placed in the fastr suite dir. Separate directories are used for FastR and GNU R package installs -and tests, namely 'lib.install.cran.{fastr,gnur}' and 'test.{fastr,gnur}' (sh syntax). +and tests, namely 'lib.install.packages.{fastr,gnur}' and 'test.{fastr,gnur}' (sh syntax). ''' from os.path import join, relpath import shutil, os, re @@ -48,17 +48,28 @@ def _mx_gnur(): return mx.suite('gnur') def _gnur_rscript(): + ''' + returns path to Rscript in sibling gnur directory + ''' return _mx_gnur().extensions._gnur_rscript_path() def _graalvm_rscript(): assert graalvm is not None return join(graalvm, 'bin', 'Rscript') +def _check_graalvm(): + if os.environ.has_key('FASTR_GRAALVM'): + return os.environ['FASTR_GRAALVM'] + elif os.environ.has_key('GRAALVM_FASTR'): + return os.environ['GRAALVM_FASTR'] + else: + return None + def _graalvm(): global graalvm if graalvm is None: - if os.environ.has_key('GRAALVM_FASTR'): - graalvm = os.environ['GRAALVM_FASTR'] + graalvm = _check_graalvm() + if graalvm: # version check gnur_version = _mx_gnur().extensions.r_version().split('-')[1] graalvm_version = subprocess.check_output([_graalvm_rscript(), '--version'], stderr=subprocess.STDOUT).rstrip() @@ -68,10 +79,10 @@ def _graalvm(): def _create_libinstall(rvm, test_installed): ''' - Create lib.install.cran.<rvm>/install.tmp.<rvm>/test.<rvm> for <rvm>: fastr or gnur + Create lib.install.packages.<rvm>/install.tmp.<rvm>/test.<rvm> for <rvm>: fastr or gnur If use_installed_pkgs is True, assume lib.install exists and is populated (development) ''' - libinstall = join(_fastr_suite_dir(), "lib.install.cran." + rvm) + libinstall = join(_fastr_suite_dir(), "lib.install.packages." + rvm) if not test_installed: # make sure its empty shutil.rmtree(libinstall, ignore_errors=True) @@ -80,39 +91,58 @@ def _create_libinstall(rvm, test_installed): # install_tmp = join(_fastr_suite_dir(), "install.tmp") shutil.rmtree(install_tmp, ignore_errors=True) os.mkdir(install_tmp) + _create_testdot(rvm) + return libinstall, install_tmp + +def _create_testdot(rvm): testdir = join(_fastr_suite_dir(), "test." + rvm) shutil.rmtree(testdir, ignore_errors=True) os.mkdir(testdir) - return libinstall, install_tmp, testdir + return testdir def _log_step(state, step, rvariant): if not quiet: print "{0} {1} with {2}".format(state, step, rvariant) -def _cran_test_project(): - return 'com.oracle.truffle.r.test.cran' +def _packages_test_project(): + return 'com.oracle.truffle.r.test.packages' + +def _packages_test_project_dir(): + return mx.project(_packages_test_project()).dir + +def _ensure_R_on_PATH(env, bindir): + ''' + Some packages (e.g. stringi) require that 'R' is actually on the PATH + ''' + env['PATH'] = join(bindir) + os.pathsep + os.environ['PATH'] -def _cran_test_project_dir(): - return mx.project(_cran_test_project()).dir def installpkgs(args): _installpkgs(args) def _installpkgs_script(): - cran_test = _cran_test_project_dir() - return join(cran_test, 'r', 'install.cran.packages.R') + packages_test = _packages_test_project_dir() + return join(packages_test, 'r', 'install.packages.R') def _installpkgs(args, **kwargs): ''' Runs the R script that does package/installation and testing. If we are running in a binary graalvm environment, which is indicated - by the GRAALVM_FASTR environment variable, we can't use mx to invoke + by the FASTR_GRAALVM environment variable, we can't use mx to invoke FastR, but instead have to invoke the command directly. ''' + if kwargs.has_key('env'): + env = kwargs['env'] + else: + env = os.environ.copy() + kwargs['env'] = env + script = _installpkgs_script() if _graalvm() is None: + _ensure_R_on_PATH(env, join(_fastr_suite_dir(), 'bin')) return mx_fastr.rscript([script] + args, **kwargs) else: + _ensure_R_on_PATH(env, os.path.dirname(_graalvm_rscript())) return mx.run([_graalvm_rscript(), script] + args, **kwargs) @@ -123,14 +153,14 @@ def pkgtest(args): ''' test_installed = '--no-install' in args - fastr_libinstall, fastr_install_tmp, fastr_testdir = _create_libinstall('fastr', test_installed) - gnur_libinstall, gnur_install_tmp, gnur_testdir = _create_libinstall('gnur', test_installed) + fastr_libinstall, fastr_install_tmp = _create_libinstall('fastr', test_installed) + gnur_libinstall, gnur_install_tmp = _create_libinstall('gnur', test_installed) if "--quiet" in args: global quiet quiet = True - install_args = args + install_args = list(args) class OutputCapture: def __init__(self): @@ -201,7 +231,7 @@ def pkgtest(args): install_args += ['--print-install-status'] _log_step('BEGIN', 'install/test', 'FastR') - # Currently installpkgs does not set a return code (in install.cran.packages.R) + # Currently installpkgs does not set a return code (in install.packages.R) rc = _installpkgs(install_args, nonZeroIsFatal=False, env=env, out=out, err=out) if rc == 100: # fatal error connecting to package repo @@ -219,7 +249,7 @@ def pkgtest(args): # in order to compare the test output with GnuR we have to install/test the same # set of packages with GnuR ok_pkgs = [k for k, v in out.install_status.iteritems() if v] - _gnur_install_test(ok_pkgs, gnur_libinstall, gnur_install_tmp) + _gnur_install_test(_args_to_forward_to_gnur(args), ok_pkgs, gnur_libinstall, gnur_install_tmp) _set_test_status(out.test_info) print 'Test Status' for pkg, test_status in out.test_info.iteritems(): @@ -227,36 +257,14 @@ def pkgtest(args): rc = rc | 2 print '{0}: {1}'.format(pkg, test_status.status) - # tar up the test results - tar_tests(fastr_testdir) - tar_tests(gnur_testdir) + diffdir = _create_testdot('diffs') + for pkg, _ in out.test_info.iteritems(): + diff_file = join(diffdir, pkg) + subprocess.call(['diff', '-r', _pkg_testdir('fastr', pkg), _pkg_testdir('gnur', pkg)], stdout=open(diff_file, 'w')) shutil.rmtree(fastr_install_tmp, ignore_errors=True) return rc -def tar_tests(testdir): - if os.environ.has_key('FASTR_TEST_GZIP'): - test_tar = testdir + '.tar' - subprocess.call(['tar', 'cf', test_tar, os.path.basename(testdir)]) - if os.path.exists(test_tar + '.gz'): - os.remove(test_tar + '.gz') - subprocess.call(['gzip', test_tar]) - else: - # workaround for lack of support for accessing gz files - with open(testdir + '.agg', 'w') as o: - for root, _, files in os.walk(testdir): - for f in files: - ext = os.path.splitext(f)[1] - if f == 'test_time' or f == 'testfile_status' or ext == '.pdf' or ext == '.prev' or ext == '.save': - continue - absfile = join(root, f) - relfile = relpath(absfile, _fastr_suite_dir()) - o.write('#### ' + relfile + '\n') - with open(absfile) as inp: - text = inp.read() - o.write(text) - - class TestFileStatus: ''' Records the status of a test file. status is either "OK" or "FAILED". @@ -286,12 +294,9 @@ def _get_test_outputs(rvm, pkg_name, test_info): test_info[pkg_name] = TestStatus() for f in files: ext = os.path.splitext(f)[1] - if f == 'test_time' or ext == '.R' or ext == '.prev': - continue # suppress .pdf's for now (we can't compare them) - if ext == '.pdf': - continue - if ext == '.save': + ignore = ['.R', '.Rin', '.prev', '.bug', '.pdf', '.save'] + if f == 'test_time' or ext in ignore: continue status = "OK" if ext == '.fail': @@ -303,7 +308,25 @@ def _get_test_outputs(rvm, pkg_name, test_info): relfile = relpath(absfile, pkg_testdir) test_info[pkg_name].testfile_outputs[relfile] = TestFileStatus(status, absfile) -def _gnur_install_test(pkgs, gnur_libinstall, gnur_install_tmp): +def _args_to_forward_to_gnur(args): + forwarded_args = ['--repos', '--run-mode'] + result = [] + i = 0 + while i < len(args): + arg = args[i] + if arg in forwarded_args: + result.append(arg) + i = i + 1 + result.append(args[i]) + i = i + 1 + return result + +def _gnur_install_test(forwarded_args, pkgs, gnur_libinstall, gnur_install_tmp): + ''' + Install/test with GNU R exactly those packages that installed correctly with FastR. + N.B. That means that regardless of how the packages were specified to pkgtest + we always use a --pkg-filelist' arg to GNU R + ''' gnur_packages = join(_fastr_suite_dir(), 'gnur.packages') with open(gnur_packages, 'w') as f: for pkg in pkgs: @@ -317,17 +340,19 @@ def _gnur_install_test(pkgs, gnur_libinstall, gnur_install_tmp): args = [] if _graalvm(): args += [_gnur_rscript()] + # forward any explicit args to pkgtest args += [_installpkgs_script()] + args += forwarded_args args += ['--pkg-filelist', gnur_packages] args += ['--run-tests'] -# GNU R will abort the entire run otherwise if a failure occurs -# args += ['--run-mode', 'internal'] args += ['--ignore-blacklist'] args += ['--testdir', 'test.gnur'] _log_step('BEGIN', 'install/test', 'GnuR') if _graalvm(): + _ensure_R_on_PATH(env, os.path.dirname(_gnur_rscript())) mx.run(args, nonZeroIsFatal=False, env=env) else: + _ensure_R_on_PATH(env, mx_fastr._gnur_path()) mx_fastr.gnu_rscript(args, env=env) _log_step('END', 'install/test', 'GnuR') @@ -422,7 +447,13 @@ def _find_start(content): for i in range(len(content)): line = content[i] if marker in line: - return i + 1 + # skip blank lines + j = i + 1 + while j < len(content): + line = content[j].strip() + if len(line) > 0: + return j + j = j + 1 return None def _find_end(content): @@ -434,6 +465,20 @@ def _find_end(content): # not all files have a Time elapsed: return len(content) - 1 +def _find_line(gnur_line, fastr_content, fastr_i): + ''' + Search forward in fastr_content from fastr_i searching for a match with gnur_line. + Do not match empty lines! + ''' + if gnur_line == '\n': + return -1 + while fastr_i < len(fastr_content): + fastr_line = fastr_content[fastr_i] + if fastr_line == gnur_line: + return fastr_i + fastr_i = fastr_i + 1 + return -1 + def _fuzzy_compare(gnur_content, fastr_content): gnur_start = _find_start(gnur_content) gnur_end = _find_end(gnur_content) @@ -441,20 +486,62 @@ def _fuzzy_compare(gnur_content, fastr_content): fastr_len = len(fastr_content) if not gnur_start or not gnur_end or not fastr_start: return -1 - gnur_start = gnur_start + 1 # Gnu has extra empty line + gnur_i = gnur_start + fastr_i = fastr_start result = 0 - i = gnur_start - while i + gnur_start < gnur_end: - gnur_line = gnur_content[i + gnur_start] - if i + fastr_start >= fastr_len: + while gnur_i < gnur_end: + gnur_line = gnur_content[gnur_i] + if fastr_i >= fastr_len: result = 1 break - fastr_line = fastr_content[i + fastr_start] + fastr_line = fastr_content[fastr_i] if gnur_line != fastr_line: - result = 1 - break - i = i + 1 + # we are fuzzy on Error/Warning as FastR often differs + # in the context/format of the error/warniong message AND GnuR is sometimes + # inconsistent over which error message it uses. Unlike the unit test environment, + # we cannot tag tests in any way, so we simply check that FastR does report + # an error. We then scan forward to try to get the files back in sync, as the + # the number of error/warning lines may differ. + if gnur_line.startswith(('Error', 'Warning')): + to_match = 'Error' if gnur_line.startswith('Error') else 'Warning' + if not fastr_line.startswith(to_match): + result = 1 + break + else: + # skip until lines match (or not) + gnur_i = gnur_i + 1 + fastr_i = fastr_i + 1 + if gnur_i == gnur_end - 1: + # at end (there is always a blank line) + break + ni = -1 + while gnur_i < gnur_end: + ni = _find_line(gnur_content[gnur_i], fastr_content, fastr_i) + if ni > 0: + break + gnur_i = gnur_i + 1 + if ni > 0: + fastr_i = ni + continue + else: + result = 1 + break + else: + # genuine difference (modulo whitespace) + if not _ignore_whitespace(gnur_line, fastr_line): + result = 1 + break + gnur_i = gnur_i + 1 + fastr_i = fastr_i + 1 return result +def _ignore_whitespace(gnur_line, fastr_line): + return gnur_line.translate(None, ' \t') == fastr_line.translate(None, ' \t') +def pkgtest_cmp(args): + with open(args[0]) as f: + gnur_content = f.readlines() + with open(args[1]) as f: + fastr_content = f.readlines() + return _fuzzy_compare(gnur_content, fastr_content) diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py index b9a1e717f21520c0b9113654e89890e1716a6a71..16bd646f2ebe8403c5c61ecc2bd36e425a978db4 100644 --- a/mx.fastr/suite.py +++ b/mx.fastr/suite.py @@ -28,9 +28,10 @@ suite = { "suites" : [ { "name" : "truffle", - "version" : "0a9e88293bf90fe485999b26b0969e71509a64aa", + "subdir" : True, + "version" : "acbe9ec935090e0824372e508563c122b0e46682", "urls" : [ - {"url" : "https://github.com/graalvm/truffle", "kind" : "git"}, + {"url" : "https://github.com/graalvm/graal", "kind" : "git"}, {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"}, ] }, @@ -40,7 +41,7 @@ suite = { "repositories" : { "snapshots" : { - "url" : "https://FASTR_SNAPSHOT_HOST/nexus/content/repositories/snapshots", + "url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "licenses" : ["GPLv2"] } }, @@ -112,7 +113,6 @@ suite = { "com.oracle.truffle.r.parser.processor" : { "sourceDirs" : ["src"], "dependencies" : [ - "JDK_TOOLS", "ANTLR-3.5", "ANTLR-C-3.5", ], @@ -196,7 +196,7 @@ suite = { "workingSets" : "FastR", }, - "com.oracle.truffle.r.test.cran" : { + "com.oracle.truffle.r.test.packages" : { "sourceDirs" : ["r"], "javaCompliance" : "1.8", "workingSets" : "FastR", @@ -210,7 +210,8 @@ suite = { "truffle:JLINE", "truffle:TRUFFLE_DEBUG", "QIR", - "PGSQL" + "PGSQL", + "truffle:TRUFFLE_NFI", ], "generatedDependencies" : [ "com.oracle.truffle.r.parser", @@ -258,11 +259,13 @@ suite = { "dependencies" : [ "GNUR", "GNU_ICONV", + "truffle:TRUFFLE_NFI_NATIVE", ], "native" : "true", - "class" : "FastRNativeProject", - "output" : "com.oracle.truffle.r.native", "workingSets" : "FastR", + "buildEnv" : { + "NFI_INCLUDES" : "-I<path:truffle:TRUFFLE_NFI_NATIVE>/include", + }, }, "com.oracle.truffle.r.library" : { @@ -306,7 +309,6 @@ suite = { "subDir" : "truffle", "dependencies" : ["com.oracle.truffle.r.parser.processor"], "exclude" : [ - "JDK_TOOLS", "ANTLR-3.5", "ANTLR-C-3.5", ], @@ -319,7 +321,6 @@ suite = { "dependencies" : ["com.oracle.truffle.r.engine", "com.oracle.truffle.r.runtime.ffi"], "mainClass" : "com.oracle.truffle.r.engine.shell.RCommand", "exclude" : [ - "JDK_TOOLS", "truffle:JLINE", "ANTLR-C-3.5", "ANTLR-3.5", @@ -330,13 +331,18 @@ suite = { "distDependencies" : [ "truffle:TRUFFLE_API", "truffle:TRUFFLE_DEBUG", + "truffle:TRUFFLE_NFI", + "truffle:TRUFFLE_NFI_NATIVE", "TRUFFLE_R_PARSER_PROCESSOR", ], }, "FASTR_UNIT_TESTS" : { "description" : "unit tests", - "dependencies" : ["com.oracle.truffle.r.test"], + "dependencies" : [ + "com.oracle.truffle.r.test", + "com.oracle.truffle.r.nodes.test" + ], "exclude": ["mx:HAMCREST", "mx:JUNIT", "mx:JMH"], "distDependencies" : [ "FASTR", @@ -351,8 +357,6 @@ suite = { "FASTR_UNIT_TESTS_NATIVE" : { "description" : "unit tests support (from test.native project)", - "dependencies" : ["com.oracle.truffle.r.test.native"], - "distDependencies" : ["FASTR_NATIVE_DEV"], "exclude" : ["GNUR", "GNU_ICONV"], "os_arch" : { "linux" : { @@ -376,35 +380,6 @@ suite = { }, }, - "FASTR_NATIVE_DEV": { - "description" : "support for overriding the native project implementation in a separate suite", - "dependencies" : ["com.oracle.truffle.r.native"], - "exclude" : [ - "GNUR", - "GNU_ICONV", - ], - "os_arch" : { - "linux" : { - "amd64" : { - "path" : "mxbuild/dists/linux/amd64/fastr-native-dev.jar", - }, - "sparcv9" : { - "path" : "mxbuild/dists/linux/sparcv9/fastr-native-dev.jar", - }, - }, - "darwin" : { - "amd64" : { - "path" : "mxbuild/dists/darwin/amd64/fastr-native-dev.jar", - }, - }, - "solaris" : { - "sparcv9" : { - "path" : "mxbuild/dists/solaris/sparcv9/fastr-native-dev.jar", - }, - }, - }, - }, - "FASTR_RELEASE": { "description" : "a binary release of FastR", "dependencies" : ["com.oracle.truffle.r.release"],